Skip to content

Microsoft 365

The Microsoft 365 tools reach OneDrive, SharePoint, Outlook mail and calendars, Microsoft To Do, Teams, OneNote, and the organization directory through Microsoft Graph as the person who asked. Each requester connects their own Microsoft account, so agents see and change only what that person can. OAuth connection mechanics shared with other providers are on OAuth Integration Framework.

Tool What it covers Provider ID Delegated Graph permissions
microsoft_files OneDrive and SharePoint files, and Excel ranges in them microsoft_files Files.ReadWrite.All
microsoft_sharepoint SharePoint sites, list items, and site pages the requester can open microsoft_sharepoint Sites.ReadWrite.All
outlook_mail The requester's Outlook mailbox and automatic replies, and shared mailboxes the requester can open outlook_mail Mail.ReadWrite, Mail.Send, Mail.ReadWrite.Shared, Mail.Send.Shared, MailboxSettings.ReadWrite
outlook_calendar The requester's Outlook calendars and events, and calendars others shared with or delegated to them outlook_calendar Calendars.ReadWrite, Calendars.ReadWrite.Shared
microsoft_todo The requester's Microsoft To Do lists and tasks microsoft_todo Tasks.ReadWrite
microsoft_teams Teams channels and chats the requester belongs to, new chats, and people's presence microsoft_teams Team.ReadBasic.All, Channel.ReadBasic.All, ChannelMessage.Read.All, ChannelMessage.Send, Chat.ReadWrite, ChatMessage.Send, Presence.Read.All, User.Read.All
microsoft_meetings Transcripts of Teams meetings the requester organized or was invited to microsoft_meetings OnlineMeetings.Read, OnlineMeetingTranscript.Read.All
microsoft_onenote OneNote notebooks of the requester, of their Teams teams and SharePoint sites, and of people who share notebooks with them microsoft_onenote Notes.ReadWrite.All
microsoft_people People, managers, and direct reports in the requester's organization directory microsoft_people User.Read.All

Every provider also requests User.Read, to label the connected account, and offline_access, to stay connected.

Set Up The Microsoft Entra App

An administrator registers one app in Microsoft Entra for the MindRoom installation, and every Microsoft 365 tool uses it.

  1. In the Microsoft Entra admin center, open App registrations and choose New registration.
  2. Under Supported account types, choose your organization only, any organization's accounts if people from several tenants connect, or also personal Microsoft accounts if people use those.
  3. Add a Web redirect URI https://mindroom.example.com/api/oauth/<provider ID>/callback for each tool you enable, such as https://mindroom.example.com/api/oauth/outlook_mail/callback, replacing the origin with your public MindRoom origin.
  4. Under Certificates & secrets, create a client secret and copy its value.
  5. Under API permissions, add the Delegated Microsoft Graph permissions from the table above for the tools you enable, plus User.Read and offline_access, and choose Grant admin consent if your tenant does not let users consent themselves.
  6. On Overview, copy the application (client) ID and the directory (tenant) ID.

ChannelMessage.Read.All and User.Read.All, which microsoft_teams requests, always need administrator consent, so nobody can connect Teams until an administrator chooses Grant admin consent on the app's API permissions page. OnlineMeetingTranscript.Read.All, which microsoft_meetings requests, likewise always needs administrator consent. User.Read.All, which microsoft_people requests, likewise always needs administrator consent before anyone can connect the people directory.

For a local installation, the redirect URIs are http://localhost:8765/api/oauth/<provider ID>/callback, such as http://localhost:8765/api/oauth/microsoft_files/callback. A hosted installation must set MINDROOM_PUBLIC_URL, from which MindRoom derives each redirect URI, and the URIs registered on the app must match exactly. Do not add application permissions; the tools only use delegated permissions, which act as the signed-in user.

Store the client ID and secret in the microsoft_oauth_client credential service through the dashboard credentials page. For non-interactive deployments, seed it at startup with a credential seed:

[
  {
    "service": "microsoft_oauth_client",
    "credentials": {
      "client_id": {"env": "MICROSOFT_CLIENT_ID"},
      "client_secret": {"env": "MICROSOFT_CLIENT_SECRET"}
    }
  }
]

To use a different app for one tool, store its credentials in that tool's <provider ID>_oauth_client service, such as microsoft_files_oauth_client, which takes precedence over microsoft_oauth_client.

Set MICROSOFT_TENANT_ID to the directory (tenant) ID or a verified domain of your organization. It defaults to organizations, which accepts any work or school account, and an app registered for your organization only requires the tenant to be set. Setting it to your tenant ID or domain limits sign-in to that tenant's accounts. consumers or common admit personal Microsoft accounts, which reach OneDrive, Outlook mail and calendars, and Microsoft To Do but not SharePoint, Teams, the people directory, or OneNote, whose Notes.ReadWrite.All personal accounts cannot grant. Changing the tenant makes existing connections ask their users to connect again.

Configure

Add the tools to an agent:

agents:
  assistant:
    tools:
      - microsoft_files
      - microsoft_sharepoint
      - outlook_mail
      - outlook_calendar
      - microsoft_todo
      - microsoft_teams
      - microsoft_meetings
      - microsoft_onenote
      - microsoft_people
Option Tool Type Default Notes
write microsoft_files boolean true Allows replacing and uploading files and writing Excel ranges; with false, those functions are not offered.
write microsoft_sharepoint boolean true Allows adding list items and changing their column values; with false, those functions are not offered.
write outlook_mail boolean true Allows creating drafts, sending new mail and replies, marking messages read or unread, moving messages, and changing automatic replies; with false, those functions are not offered.
write outlook_calendar boolean true Allows creating, changing, deleting, and answering events; with false, those functions are not offered.
write microsoft_todo boolean true Allows creating, updating, completing, and deleting tasks; with false, those functions are not offered.
write microsoft_teams boolean true Allows sending channel posts, channel replies, and chat messages, and starting chats; with false, those functions are not offered.
write microsoft_onenote boolean true Allows creating pages and appending text to pages; with false, those functions are not offered.

The scopes stay the same with write: false, so turning writes back on does not need new consent. microsoft_meetings and microsoft_people only read, so they have no write option.

Connect An Account

When a requester has not connected a tool's service yet, each of its functions returns oauth_connection_required: true with a connect_url for that requester. The requester opens the link, signs in to Microsoft, approves the requested permissions, and retries the request. Users can also connect and disconnect from the dashboard Integrations page, where each service is a separate connection. The Connections portal can connect most of an agent's unconnected Microsoft 365 services with one sign-in.

Tokens belong to the requester and are never shared with other users or stored globally. A call without a concrete requester always asks for a connection instead of using another account. Microsoft ends a connection that has not been used for 90 days, and the requester then connects again.

Files

Function Changes data Purpose
microsoft_files_search no Search the OneDrive and SharePoint files the requester can open, by name and content, up to 50 results.
microsoft_files_list_folder no List a folder's files and folders, or the requester's OneDrive root, up to 200 entries.
microsoft_files_get_file no Read a file's details, including its etag, web link, size, and last editor.
microsoft_files_download_file no Save a file, up to 100 MB, into the workspace's microsoft-files-downloads/ directory.
microsoft_files_replace_file yes Replace a file's contents with a workspace file, up to 250 MB, given the etag the edit started from.
microsoft_files_upload_file yes Upload a workspace file, up to 250 MB, as a new file in a folder or the requester's OneDrive root.
microsoft_files_excel_list_worksheets no List the worksheets of an Excel workbook.
microsoft_files_excel_read_range no Read a worksheet range, or its used range, up to 10,000 cells.
microsoft_files_excel_update_range yes Write values or formulas into a worksheet range, up to 10,000 cells.

Functions name a file or folder by its Graph item path, /drives/{drive-id}/items/{item-id}, which search, listing, and details return, or by a OneDrive or SharePoint link the requester can open. Replacing a file, uploading into a folder, and writing a range also take the target's web_url from its details, download, or folder listing (search results show another form) as expected_web_url, so an approval card shows where the write lands, and fail with target_mismatch, naming the target's web_url, when it differs. Uploads read from the agent's workspace and follow its file_access setting, and downloads always land in the workspace.

To edit a document, the agent downloads it, saves its edited copy under a new name outside microsoft-files-downloads/, and replaces the original with the etag from the download. The replace then fails with etag_mismatch if someone changed the file in the meantime, and the file's version history keeps the replaced version. A later download of the same name overwrites the copy in microsoft-files-downloads/. Uploads never overwrite an existing file; a name that already exists returns name_conflict.

Excel functions work on .xlsx workbooks in OneDrive for work or school and SharePoint. They take a worksheet name and an address such as B2 or A1:C10 without a worksheet prefix, and written values must have the shape of the address. A written string that starts with = becomes a formula.

Search uses Microsoft Search, which covers work and school accounts. Search and folder listings return a next_page_token while more results exist; passing it back continues the same search or listing.

SharePoint

Function Changes data Purpose
microsoft_sharepoint_search_sites no Search the SharePoint sites the requester can open by keyword.
microsoft_sharepoint_get_site no Get a site from its address, such as https://contoso.sharepoint.com/sites/team.
microsoft_sharepoint_list_lists no List a site's lists and document libraries, leaving out hidden and system lists.
microsoft_sharepoint_get_list no Read a list with its columns: internal name, display name, type, and whether each is required or read-only.
microsoft_sharepoint_list_items no List up to 50 items of a list with their column values, each text value up to 4,000 characters.
microsoft_sharepoint_create_item yes Add an item to a list with the given column values.
microsoft_sharepoint_update_item yes Change column values of a list item; columns not given stay unchanged.
microsoft_sharepoint_list_pages no List a site's pages and news posts.
microsoft_sharepoint_get_page no Read a page as plain text, its title and then its text web parts in layout order, in chunks of up to 30,000 characters.

The tool covers sites, lists, list items, and pages; files and the files in document libraries stay with microsoft_files. List items take and return column values keyed by each column's internal name, which microsoft_sharepoint_get_list reports next to the display name. A lookup or person column is written as its name plus LookupId, such as OwnerLookupId, with the lookup ID. A multi-value column takes a list, together with <name>@odata.type set to Collection(Edm.String) for text or Collection(Edm.Int32) for lookup IDs. Adding and changing items also take the list's web_url from microsoft_sharepoint_list_lists or microsoft_sharepoint_get_list as expected_web_url, so an approval card shows which list the write lands in, and fail with target_mismatch, naming the list's web_url, when it differs. Site addresses must be the site itself, without a page, list, or library path after it. Page text leaves out web parts that are not text, such as image or embedded document parts, and images inside text show as [image]. Site, list, item, and page listings, and long pages, return a next_page_token while more exists; passing it back continues the same listing or page.

Mail

Function Changes data Purpose
outlook_mail_search no List messages newest first, in one folder or across the mailbox, optionally matching an Outlook search query, up to 50 results.
outlook_mail_get_message no Read a message as plain text, up to 20,000 characters, with its recipients and attachment list.
outlook_mail_download_attachment no Save a file attachment, up to 50 MB, into the workspace's outlook-mail-attachments/ directory.
outlook_mail_create_draft yes Save a new plain-text draft, optionally with workspace files attached, without sending it.
outlook_mail_send yes, sends mail Send a new plain-text message at once, optionally with workspace files attached.
outlook_mail_reply yes, sends mail Reply to the sender, or to everyone with reply_all, above the quoted original; the original's reply-to addresses, when set, take the sender's place.
outlook_mail_mark_read yes Mark a message read or unread.
outlook_mail_move yes Move a message to a folder.
outlook_mail_get_automatic_replies no Read whether the requester's automatic replies (out of office) are off, on, or scheduled, with their period and messages.
outlook_mail_set_automatic_replies yes Turn the requester's automatic replies off, on, or on for a period, and set the messages for people inside and outside the organization.

Search takes Outlook search syntax, such as from:sam@example.com subject:"quarterly plan" hasAttachments:true. Search returns a next_page_token while more messages exist; passing it back continues the same listing or search. A search with query stops after its first 1,000 matches, so a narrower query finds the rest. Folders are named by a well-known name, inbox, sentitems, drafts, archive, deleteditems, or junkemail, or by a folder ID, such as a message's parent_folder_id. Messages and replies are plain text, and sent mail is saved in the sending mailbox's Sent Items. A new message takes at most 50 email addresses across To and Cc. To review a message before it goes out, ask for a draft; its web_link opens it in Outlook, where the requester sends it.

Every function except the automatic replies ones takes an optional mailbox: the email address of a shared mailbox, or of a person who gave the requester access to their mailbox, to act in instead of the requester's own. Exchange permissions on that mailbox decide what works: reading and changing its messages needs access to them, such as Full Access, and sending from it, as a new message or a reply, needs Full Access plus Send As or Send on Behalf. With Send As, recipients see mail from the mailbox itself; with Send on Behalf, they see that the requester sent it on the mailbox's behalf. A missing permission fails with forbidden, and Microsoft Graph cannot list which mailboxes a requester may open. Message IDs and page tokens belong to the mailbox that returned them, so pass the same mailbox again. A call with mailbox repeats it in every result, errors included.

Automatic replies are always the requester's own. Their messages are plain text, and a scheduled period takes a local start and end with a time zone, like a new calendar event; Outlook schedules only a period that has not ended yet. Turning them on names the internal message and an external audience of internal_only, contactsOnly, or all, plus the external message unless the audience is internal_only, so an approval card shows everything senders get. Outlook Mail asks a requester to connect again when their connection lacks any of the permissions above.

Attachments are workspace files and follow the agent's file_access setting. Each attached file may be at most 3 MB, and all attachments of one message together about 3 MB; share larger files through OneDrive and send a link instead. Only file attachments can be downloaded, not attached Outlook items such as forwarded messages or invitations, and not cloud links. A later download of the same attachment name overwrites the copy in outlook-mail-attachments/.

Calendar

Function Changes data Purpose
outlook_calendar_list_calendars no List the requester's calendars, whether the requester can edit each, and which one is the default.
outlook_calendar_list_events no List events between two moments in the default calendar or another, in start order, up to 50, with attendees and their responses and the online meeting link.
outlook_calendar_get_event no Read an event with its description as plain text, up to 20,000 characters.
outlook_calendar_get_free_busy no Look up when up to 20 colleagues, distribution lists, or rooms are busy, with their working hours, to find a time to meet.
outlook_calendar_create_event yes Create an event, optionally with attendees, a location, a description, and an online meeting; Outlook emails each attendee an invitation.
outlook_calendar_update_event yes Change an event's subject, start, end, location, or description; attendees of a meeting the requester organizes receive the update.
outlook_calendar_delete_event yes Delete an event; for a meeting the requester organizes, Outlook sends every attendee a cancellation.
outlook_calendar_respond_to_event yes Accept, tentatively accept, or decline a meeting invitation, optionally with a comment to the organizer.

Event times in event results are in UTC, and the agent converts them to the requester's time zone. A listing window may span at most 366 days. Calendar and event listings return a next_page_token while more results exist; passing it back continues the same listing. New and changed events take local times plus a time zone, either a Windows name such as W. Europe Standard Time or an IANA name Outlook accepts such as Europe/Berlin. Free/busy lookups take local times plus a time zone, like new events, and return times in that zone. A free/busy window must be shorter than 62 days, and each member of a distribution list counts toward the 20. Free/busy shows another person's event subjects and locations only when their calendar sharing allows it, and it needs a work or school account. Each occurrence of a recurring meeting has its own ID, and changing or deleting an occurrence affects only that occurrence. Responding to the series master, whose ID each occurrence carries as series_master_id, answers the whole series. Changing or deleting the series master changes or deletes every occurrence. Deleting a meeting the requester only attends removes it from their calendar without telling the organizer; declining it tells the organizer. Responding to a meeting also takes the organizer's email from the event as expected_organizer, so an approval card shows who receives the response, and fails with target_mismatch, naming the real organizer, when it differs. A new event can invite at most 100 attendees. The description of an online meeting cannot be replaced, because that would remove its join link; edit it in Outlook instead.

Listing calendars and events, reading an event, and creating, changing, and deleting events also take an optional calendar_owner: the email address or sign-in name of another person whose calendar the requester can open in Outlook because that person shared it with them or made them a delegate. Reading needs at least read access to that calendar and writing needs edit or delegate access; otherwise Microsoft Graph answers forbidden or not_found. Calendar IDs, event IDs, and page tokens from such a call belong to that person's mailbox, so follow-up calls pass the same calendar_owner, and a page token from another mailbox fails with invalid_page_token. A calendar shared with the requester can also appear in their own calendar list, with that person as owner, and its ID works without calendar_owner. On another person's calendar, that person organizes a new event, and Outlook sends its invitations, updates, and cancellations in that person's name, sent by the requester on their behalf. A call with calendar_owner shows it on its approval card and repeats it in every result, errors included. Responding to invitations covers only the requester's own invitations, and free/busy already looks up other people. Calendars.ReadWrite.Shared needs no administrator consent; calendar connections made before the tool requested it lack it, so each requester reconnects once.

To Do

Function Changes data Purpose
microsoft_todo_list_lists no List the requester's task lists, including lists shared with them, and whether the requester owns each.
microsoft_todo_list_tasks no List up to 50 open tasks of one list, or completed ones too when asked, with notes up to 2,000 characters each.
microsoft_todo_create_task yes Create a task with a title and, optionally, a due date, notes, and importance.
microsoft_todo_update_task yes Change a task's title, due date, notes, or importance, or mark it completed or not started again.
microsoft_todo_delete_task yes Delete a task.

The lists include the requester's default Tasks list and the list of flagged Outlook messages. New and changed due dates take a calendar date and become midnight in the time_zone the agent passes, which should be the requester's zone and defaults to UTC. Listed, created, and updated tasks return the due date, time, and zone Graph reports; a due date is midnight in the zone of whoever set it, which Graph usually reports in UTC, so the agent converts it to the requester's zone before naming the day. List and task listings return a next_page_token while more results exist; passing it back continues the same listing. Updating a task's notes replaces them completely.

Teams

Function Changes data Purpose
microsoft_teams_list_teams no List the teams the requester is a member of, and whether each is archived.
microsoft_teams_list_channels no List the channels of one team that the requester can see, and whether each is archived.
microsoft_teams_list_channel_messages no List up to 50 top-level posts of one channel, without their replies, most recently active thread first.
microsoft_teams_list_channel_message_replies no List up to 50 replies in the thread of one channel post.
microsoft_teams_list_chats no List up to 50 of the requester's one-on-one, group, and meeting chats, with member names and email addresses, most recent message first.
microsoft_teams_list_chat_messages no List up to 50 messages of one chat, newest first.
microsoft_teams_get_presence no Read the availability, activity, and status message of up to 20 people.
microsoft_teams_send_channel_message yes, posts to the channel Post a new message in a channel.
microsoft_teams_reply_to_channel_message yes, posts to the channel Reply in the thread of a channel post.
microsoft_teams_send_chat_message yes, posts to the chat Send a message in an existing chat.
microsoft_teams_start_chat yes, creates a chat and posts to it Start a chat with up to 20 people and send its first message.

Messages come back as plain text, up to 4,000 characters each. Deleted messages and system events, such as members joining, come back labeled, without text. Channel, chat, and message listings return a next_page_token while more results exist; passing it back continues the same listing. Sent messages appear under the requester's name and keep their line breaks, and HTML in the text shows literally instead of as formatting. A sent message holds up to 28,000 bytes once its text is HTML-escaped. A chat message takes the email address of every chat member, the requester's own included, as recipients, and a channel post or reply takes the team and channel names as expected_team and expected_channel, so an approval card shows who reads the message. When a member's email address is missing or not listed, or a name differs, nothing is sent and the call fails with recipients_mismatch, listing every member, or target_mismatch, naming the real team and channel. Starting a chat takes the other people's sign-in addresses (userPrincipalName), usually their email addresses, so its approval card shows who reads the first message. One person gives a one-on-one chat, and Teams keeps one per pair, so the message lands in the existing one-on-one chat when there is one; two or more people give a new group chat, which can have a topic. Before posting, it reads the chat's members and sends nothing, failing with recipients_mismatch and the chat_id, when a member's email address is missing or differs from the addresses given. Presence looks up each person's user id by sign-in address, reports a person Microsoft Graph cannot find or show with not_found or forbidden without failing the others, and returns status messages as plain text. Connections made before microsoft_teams requested Chat.ReadWrite, Presence.Read.All, and User.Read.All ask their users to connect again once. The tool sees private and shared channels only when the requester is a member. Shared channels from a team the requester is not a member of are not reachable.

Teams Meetings

Function Changes data Purpose
microsoft_meetings_find no Find the Teams meeting behind a join link, with its subject, times, organizer, and expiry.
microsoft_meetings_list_transcripts no List the transcripts of one meeting, with when each was created and ended.
microsoft_meetings_get_transcript no Read one transcript as timestamped lines labeled with their speaker, up to 30,000 characters per call.

To read a meeting's transcript, the agent takes the event's join_url from outlook_calendar_list_events or outlook_calendar_get_event, finds the meeting, lists its transcripts, and reads one. Transcript lines look like 00:12:03 Alex Doe: text, timed from the start of transcription, with each speaker's consecutive sentences joined into lines of up to about 2,000 characters. A long transcript comes back in chunks with a next_page_token; passing it back continues the same transcript, and transcript listings page the same way. A recurring meeting series is one meeting, so its listing holds a transcript for each occurrence that was transcribed.

Transcripts exist only for meetings in which someone turned on transcription. Microsoft Graph serves them only to the meeting's organizer and the people its calendar invite names, only for meetings scheduled with a calendar event, and not for live events. Graph no longer serves the transcripts of an expired meeting; a one-time meeting expires 60 days after its scheduled time, extended by 60 days whenever someone joins or changes it, and microsoft_meetings_find reports when a meeting expires. Two Teams administrator settings also govern transcripts: with Graph access to transcripts turned off, listing and reading transcripts return transcripts_disabled, and with speaker attribution turned off, reading a transcript returns speaker_attribution_disabled.

OneNote

Function Changes data Purpose
microsoft_onenote_list_notebooks no List the notebooks the requester owns, or those of a team, a site, or a person who shares them, by name, and which one is the default.
microsoft_onenote_list_sections no List the sections directly in one notebook, by name.
microsoft_onenote_list_pages no List up to 50 pages of one section, most recently modified first, with titles and dates.
microsoft_onenote_get_page no Read a page's content as plain text, 30,000 characters at a time.
microsoft_onenote_create_page yes Create a page with a title and plain-text content in a section.
microsoft_onenote_append_to_page yes Add plain text as a new paragraph at the end of a page's first block of content.

Without container, the functions reach the notebooks the requester owns. Every function also takes an optional container naming where other notebooks are, told apart by its form: a Teams team's id from microsoft_teams_list_teams (a team's id is its Microsoft 365 group's id), a SharePoint site's id from microsoft_sharepoint_search_sites or microsoft_sharepoint_get_site (host,guid,guid), or a person's sign-in email address (user principal name) for the notebooks that person shares with the requester. A bare id always names a team, so a person is named by sign-in email address and not by id; a container of any other form is refused before any request. Results repeat the container, and calls on the sections and pages of those notebooks pass it again; Notes.ReadWrite.All already covers every notebook the requester can open, so containers need no new consent. Sections inside section groups are not listed. Page text leaves out the title, shows images as [image], and separates table cells with |. Listings and page text return a next_page_token while more follows; passing it back with the same container and the same notebook, section, or page continues. Created and appended text keeps its line breaks, and HTML in it shows literally instead of as formatting. Creating and appending also take the web_url of the notebook they write into, from microsoft_onenote_list_notebooks, as expected_web_url, so an approval card shows whose notebook the write lands in, and fail with target_mismatch, naming the notebook's web_url, when it differs.

People

Function Changes data Purpose
microsoft_people_search no Find people in the organization directory by name or by the beginning of their email address, up to 50 results.
microsoft_people_get_profile no Read one person's profile and their manager.
microsoft_people_list_direct_reports no List the people who report directly to one person.

Agents use these functions to turn a name the requester mentions into a person and an email address for the mail, calendar, and Teams tools. Each person comes back with their id, name, email address, job title, department, office location, and business phones; mobile phones and other personal fields are never read. The email address is the person's primary email address, or their sign-in name when they have none. Profile and direct report lookups take a person's id, email address, or sign-in name, or me for the requester, so "who is my manager" needs no email address. Search matches names by whole words or their beginnings in any order, and email addresses from their beginning, and someone added to the directory in the last few minutes may not show up yet. A person without a manager, or whose manager is a contact instead of a user, comes back with manager set to null, and direct report listings leave out contacts. Direct report listings return a next_page_token while more results exist; passing it back continues the same listing. Guest accounts cannot search the directory.

Approvals For Writes

The tools run without approval unless you add tool approval rules, which show a Matrix approval card before each change:

tool_approval:
  rules:
    - match: microsoft_files_replace_file
      action: require_approval
    - match: microsoft_files_upload_file
      action: require_approval
    - match: microsoft_files_excel_update_range
      action: require_approval
    - match: microsoft_sharepoint_create_item
      action: require_approval
    - match: microsoft_sharepoint_update_item
      action: require_approval
    - match: outlook_mail_send
      action: require_approval
    - match: outlook_mail_reply
      action: require_approval
    - match: outlook_mail_set_automatic_replies
      action: require_approval
    - match: outlook_calendar_create_event
      action: require_approval
    - match: outlook_calendar_update_event
      action: require_approval
    - match: outlook_calendar_delete_event
      action: require_approval
    - match: outlook_calendar_respond_to_event
      action: require_approval
    - match: microsoft_todo_create_task
      action: require_approval
    - match: microsoft_todo_update_task
      action: require_approval
    - match: microsoft_todo_delete_task
      action: require_approval
    - match: microsoft_teams_send_channel_message
      action: require_approval
    - match: microsoft_teams_reply_to_channel_message
      action: require_approval
    - match: microsoft_teams_send_chat_message
      action: require_approval
    - match: microsoft_teams_start_chat
      action: require_approval
    - match: microsoft_onenote_create_page
      action: require_approval
    - match: microsoft_onenote_append_to_page
      action: require_approval

Sent mail cannot be recalled, so require approval at least for outlook_mail_send and outlook_mail_reply, and likewise for the Teams send functions, whose messages everyone in the channel or chat sees at once. The approval cards of both mail functions list every recipient, and a reply is sent only to the recipients its card lists. A card without mailbox sends as the requester; with it, the card names the shared mailbox the mail goes out from. outlook_mail_create_draft, outlook_mail_mark_read, and outlook_mail_move change only the mailbox they name, the requester's own by default, where they can be undone; colleagues who share a mailbox see those changes too. Automatic replies answer every sender while they are on, outside the organization too when external_audience allows it. Every calendar write can email invitations, updates, cancellations, or responses to other people.

To give an agent read access only, set write: false on the tool.

Troubleshooting

Result Cause and fix
AADSTS50011 on the Microsoft sign-in page The redirect URI is not registered on the app; add the exact URI from Set Up The Microsoft Entra App.
AADSTS65001 or a consent prompt the requester cannot approve The tenant requires administrator consent, which Teams, Teams meeting transcripts, and the people directory always do; an administrator grants it on the app's API permissions page.
AADSTS50194 The app is registered for one organization; set MICROSOFT_TENANT_ID.
invalid_tenant MICROSOFT_TENANT_ID is not a tenant ID, a verified domain, organizations, common, or consumers.
forbidden The connected account lacks access to that item, such as a shared mailbox without the Exchange permission, which reconnecting does not fix.
not_found The item does not exist or the connected account cannot see it, or the Teams meeting expired.
invalid_file The value is neither a Graph item path nor a OneDrive or SharePoint link.
invalid_argument An argument is malformed or exceeds a limit above, such as an ID, folder, email address, time, or time zone, or an end that is not after its start; the message names the field.
invalid_local_path An upload or attachment path is not an existing file the agent's file_access allows.
online_meeting_unavailable The calendar has no default online meeting provider, such as Teams, so the event cannot get a join link; create it without an online meeting.
online_meeting_body The update tried to replace an online meeting's description; change the other fields, or edit the description in Outlook.
meeting_not_found No Teams meeting with that join link is visible to the requester, such as a meeting they neither organized nor were invited to.
no_transcripts Nobody turned on transcription in the meeting, or Teams has not finished saving the transcript yet.
no_calendar_event The meeting was created without a calendar event, such as by an app, and Microsoft Graph serves no transcripts for it.
transcripts_disabled A Teams administrator turned off Microsoft Graph access to meeting transcripts; only an administrator can turn it back on.
speaker_attribution_disabled A Teams administrator turned off speaker attribution for transcripts, and microsoft_meetings reads transcripts only with their speakers.
not_a_file_attachment The mail attachment is an attached Outlook item or a cloud link, which cannot be downloaded.
etag_mismatch The file changed since the etag was read; download it again and redo the edit.
locked The file is checked out or locked; try again later.
name_conflict A file with that name already exists in the folder; replace it or choose another name.
too_large The file, range, attachment, or message exceeds a limit above; send a OneDrive link instead of a large attachment.
throttled Microsoft Graph is limiting requests; retry after retry_after_seconds.
download_rejected SharePoint refused the download link Microsoft Graph returned; retry the download.
graph_error Microsoft Graph refused the request, such as a time zone Outlook does not support or a response to a meeting the requester organizes; graph_code and graph_message give Microsoft Graph's reason.

Apart from throttled, errors that Microsoft Graph returns carry its error code as graph_code and, when Graph gives one, its reason as graph_message: one line of plain text without links, cut to 300 characters. When Microsoft rejects the connection's access token, the result includes a reconnect link.

Security Notes

  • The tools run in the primary MindRoom runtime, so worker containers never receive the app client configuration or user tokens.
  • Tokens are sent only to Microsoft Graph, never to another host, including the SharePoint hosts that serve downloads.
  • Request logs never contain tokens or pre-authenticated download links.
  • Error results never contain tokens or raw response bodies, only Graph's error code and its trimmed reason.