Skip to content

Integrations

This page complements Integrations in XTM One.

That guide explains when integrations matter. This page gives you a quick tour of the integration screens.

Each first-party provider card in the integration catalog carries a diagonal corner ribbon. Certified marks the integrations Filigran qualifies and supports: OpenCTI, OpenAEV, OpenCRQ (the product marketed as OpenCRQ), and the XTM Hub. Preview marks every other catalog entry. Custom providers you import yourself carry no ribbon — the qualification is ours to make about our own catalog, not about your bundles — and are identified by their Custom badge instead.

The list page

In the left navigation, this area is Integrations. The list page answers one practical question fast: which external connections are usable right now.

Each card is status-heavy by design, so the list already works as a health dashboard. The status badge is the signal to read first — it distinguishes a connection that is ready, one that is configured but not yet authorized, and one that needs re-authorization because permissions changed or the provider refused its refresh token or client credentials. You can search by name or provider and filter by visibility, tags, or category to narrow a long list.

If you have permission, New Integration starts a new connection. Credentials are always encrypted in the database.

The detail page

Opening an integration shows a header with the connection status and the actions that make sense for it — a setup guide for provider prerequisites, Test Connection to validate the live connection, Authorize or Re-authorize to resolve OAuth state, and delete. The detail page itself is organized into Overview, Configuration, and Activity tabs.

When an integration is built on an open-source project, its setup guide credits that project under the title: its name links to the project's repository, followed by its author and its license. The Nova integration, for example, credits NOVA by Thomas Roccia, released under the MIT license; see Prompt safety (Nova).

Some integrations add pages of their own after those three tabs — the API Spec of an integration imported from an OpenAPI or Swagger document, or the rules of the Nova integration, which only administrators see. These pages are tabs of the integration: open the integration from Tools & Integrations > Integrations to reach them. Integrations are never listed one by one in the left navigation. Anyone who opens such a page from a link without being allowed to see it is told it is not available to them, with a way back to the Overview.

When Test Connection reports a failure the platform recorded earlier - such as the last rule sync of the Nova integration - the stored error is shown only to the people who can manage the integration (administrators, for a company-managed integration). Everyone else sees that the check failed and a sentence saying who can see the details; the server log always keeps the full error.

Overview

Overview tells you not only whether the integration works, but why it does or does not. It combines usage figures, the connection state (authentication method, credential readiness, authorized and missing scopes), and cards showing which agents — and, for sync sources, which knowledge bases — depend on it.

Configuration

Configuration is a richer screen than most other resources because it mixes three concerns: the integration's identity, its authentication and provider setup, and its visibility and reuse in the workspace. The description field matters more than it looks — the UI passes it to agents as tool context.

This tab is also where you see what the integration actually does:

  • The available tools are split into read tools (retrieve or inspect information) and write tools (change something in the connected system). That split helps you judge risk. When the integration is connected, you can test a tool with real credentials before binding it to an agent.
  • If the provider supports events, an event triggers card explains, in business language, which external changes an agent can react to and how they are delivered (webhook, polling, or hybrid).
  • A webhooks card shows how external events enter XTM One. Depending on the provider it can display a URL to copy or, for GitHub, let you create and remove repository webhooks directly from the UI. What it shows follows the provider and the OAuth app the integration uses:
    • Microsoft 365: new emails and Teams messages are picked up by polling every 5 minutes, so there is no webhook to configure.
    • Slack: new messages are picked up by polling every 5 minutes. For real-time events, the card shows the shared Slack notifications endpoint to set as the Request URL in the Event Subscriptions of the Slack app the integration uses; the integration's Signing secret field (or, on your administrator's Slack app, the Slack OAuth default's) is what verifies them. See Slack message events below.
    • Other providers with events: an integration created on your administrator's OAuth app (you left its client ID empty and the administrator configured OAuth defaults for the provider) gets its events through the webhook the administrator set up, so the card says so instead of showing a URL. An integration on your own OAuth app shows its own webhook URL to configure in that app.
    • Replacing the client ID moves an integration to your own OAuth app. The tokens issued to the previous app are removed, so authorize the integration again before it is used.
    • For integrations created before XTM One recorded which OAuth app they use, the card compares the integration's client ID with the administrator's current OAuth default: the same ID means the administrator's app, any other means your own. Only when that comparison cannot be made does the card follow whether the provider has OAuth defaults, as it did before.

Slack message events

New Slack message assignments receive messages in two ways. The event poller reads the monitored channels every 5 minutes with the integration's own token. It needs no setup and serves every assignment whose trigger names the integration (the assignment editor always sets one) or whose agent is bound to it. For real-time delivery, the Slack app the integration runs on sends its Events API deliveries to /api/v1/integrations/notifications/slack.

That endpoint checks every delivery against the app's Signing Secret (Slack app > Basic Information). Nothing has to be set up for events to keep arriving: with no Signing Secret stored, a delivery is accepted without a verified signature, exactly as before signatures were checked, and XTM One says so with a warning in the log and a Security Audit finding. Storing the secret turns verification on for the integrations of that app:

  • An integration running on its own Slack app: put the secret in the integration's Signing secret field.
  • An integration created with the Slack app your administrator provides (Settings > OAuth defaults): the administrator stores the secret in the Signing secret field of the Slack OAuth default, once for everyone.

Once a Signing Secret is stored, a delivery it does not prove never reaches the integrations of that app, and a verified event reaches only what it concerns:

  • It reaches only the integrations running on the app that signed it, and only those of the Slack workspace it was sent for.
  • It then reaches the assignments whose agent is connected to one of those integrations, under the rules the poller applies: for an OAuth integration bound to the agent, the token is the agent owner's own, or shared with its owner's explicit acknowledgement. An assignment whose acting user can no longer see the integration still receives the event, as polled events are delivered, and the log says so.
  • A message outside a public channel (private channel, direct or group message) reaches only the integration of its author or of the user Slack authorized the event for. Everyone else still receives it through the poller if their own token can read it.
  • The trigger's channel selection applies, as the poller applies it.
  • An assignment whose agent is connected to no Slack integration at all has no app or workspace to be matched against: it receives the event as before.

An event the platform cannot verify with what it holds (no usable Signing Secret for the app that sent it) is handed out as before signatures were checked: to every New Slack message assignment whose channel selection admits it, except those connected only to integrations whose app Signing Secret is stored.

Each message runs an assignment once. The real-time path and the poller claim it under the same key, and a Slack retry of the same event is skipped. A message an assignment's own run posted does not run that assignment again; any other assignment watching the channel still runs on it.

To refuse every event that cannot be verified, an administrator turns on Require verified integration notifications in Settings > Security (or sets INTEGRATION_NOTIFICATIONS_REQUIRE_VERIFICATION=true, which wins and locks the field). The messages of integrations without a stored Signing Secret then arrive through the poller only, and the Security Audit says how many integrations are concerned. If Slack disabled the app's Event Subscriptions after refused deliveries, re-enable them once the secret is stored.

OpenRouter

The OpenRouter integration connects an OpenRouter account - one API key for hundreds of models. It takes the account's API key and, optionally, a management key (OpenRouter > Settings > Management keys): the management key cannot run models, but it unlocks the credits, the activity and the API key management below. Test Connection checks both keys.

Its three pages, tabs of the integration shown to the people who manage it:

  • Usage - what the key spent today, this week and this month, its spending limit, the credits left on the account, and the spend per day and per model over the last 30 days, with the providers that served each model.
  • Models - the catalog the key may use (text and embedding models): prices per million tokens, context, tool calling, reasoning, image input, and for each model the providers serving it with their price, uptime and latency. An administrator uses it to feed the platform's OpenRouter LLM provider: offer the models you want, mark the default one, and create the provider - or link an OpenRouter provider made in Settings > AI Models. The provider keeps a copy of the integration's API key, replaced whenever the key is replaced in the integration, and the context window of every newly offered model is taken from OpenRouter's catalog. Only a company-managed integration can feed the platform provider: the provider is shared by every user. Making the integration private again, unlinking it or deleting it leaves the provider running on the key it holds. In Settings > AI Models such a provider carries an Integration badge that leads back here.

The integration's Overview says whether the platform runs on it: the provider it feeds and its models, or, for an administrator, what is missing and a link to the Models page that creates it. Adding an OpenRouter provider in Settings > AI Models while a company-managed OpenRouter integration holding its API key feeds none points there too, so the key is not entered a second time. - API Keys - the keys of the account (management key): their spend, limit and expiry. The holder of the account - an administrator for a company-managed integration, its owner otherwise - can create a key with its own spending limit and reset period, rename it, change its limit, disable it or delete it. A new key is shown once; XTM One does not keep it. The key the integration runs on, and the key of the platform LLM provider, cannot be disabled or deleted from here.

Microsoft 365: Teams meeting recording and recurring events

The Microsoft integration's calendar tools act as the account that authorized it, on its default calendar or on any calendar passed as calendar_id (a secondary calendar, or one shared with the account).

  • Recording and transcription. When an agent creates or updates a Teams meeting, it can turn on Record and transcribe automatically, and allow or block transcription and recording. The tool changes the event's Teams meeting, then reads the options back from Microsoft and reports what Teams kept: when Teams does not keep a change (a Teams meeting policy of the organizer can forbid recording or transcription), the agent gets an error, never a success. Reading an event also shows its Teams meeting options: recording, transcription, who can bypass the lobby and who can present.
  • Recurring series. An agent can create a daily, weekly, monthly or yearly series, list its occurrences between two dates (with the ones already cancelled), and move or cancel one occurrence without touching the rest. Cancelling a meeting the account organizes sends its attendees a cancellation notice, with an optional message. A series has one Teams meeting, so its recording options cover every occurrence.

Only the organizer of a meeting can change its options, so connect the integration with the account that organizes the meetings (a dedicated service mailbox, for example). The options use the delegated Microsoft Graph permission OnlineMeetings.ReadWrite, which the integration requests; acting as the signed-in account, it needs no Teams application access policy. If a tool answers that the token lacks OnlineMeetings.ReadWrite (for example in a tenant where users cannot consent to it), an administrator adds it to the delegated permissions of the integration's app registration in Microsoft Entra ID and grants admin consent, then the integration is re-authorized (Re-authorize on its page) so its new token carries the permission.

Microsoft 365: Teams meeting transcripts

An agent reads what was said in a Teams meeting from its transcript, as the account that authorized the integration: in meetings it organized and in meetings it was invited to. Each line names its speaker.

  • Why there is no transcript. When Microsoft lists no transcript for a meeting, the agent gets Microsoft's reason and message: either Microsoft exposes no transcript for the meeting, or Microsoft refused to list it. A refusal is a permission problem, not a missing transcript, and the answer names the permission to grant, OnlineMeetingTranscript.Read.All. Listing recent transcripts counts the refused meetings apart from the meetings without a transcript.
  • From the recording. A transcribed meeting also keeps its transcript inside its recording: it is what the Teams player shows. When Microsoft lists no transcript, the join-URL transcript tool reads the one inside the meeting's recording, in the Recordings folder of your OneDrive (whatever its name in your language), where Teams saves an automatic recording of a meeting you organize. The answer names the recording it read, and the other recordings made at that time if there are any.
  • From a recording link. get_microsoft_recording_transcript reads the transcript of a recording from its OneDrive or SharePoint link (a sharing link or the address of the video), or finds a meeting's recording in your OneDrive from the meeting ID. Use the link for a recording saved in someone else's OneDrive: Teams saves a recording in the OneDrive of the person who started it.
  • Only the transcript is read: the video is never downloaded.
  • Reading the transcript inside a recording goes through SharePoint, so it needs the delegated permission AllSites.Read (Office 365 SharePoint Online) on the integration's app registration, like the transcripts of channel meetings. If the agent answers that it could not obtain a SharePoint access token, an administrator adds that permission in Microsoft Entra ID and grants admin consent, then the integration is re-authorized (Re-authorize on its page).

Microsoft 365: reading a Teams message in full

When an agent lists a Teams channel or chat, it sees each message whole, up to 4,000 characters of text (an administrator can change this with MICROSOFT_TEAMS_MESSAGE_TEXT_LIMIT, see Configuration). A longer message, such as a memo with sections and lists, is cut at the end of a word and ends with a note: [truncated, N more characters: read it in full with get_microsoft_channel_message(team_id=..., channel_id=..., message_id=...)]. The note names the exact call, with the message's own IDs, so the agent can read the rest. A message without the note is complete.

  • One message, in full. get_microsoft_channel_message reads one post or thread reply of a channel, and get_microsoft_chat_message one message of a chat. The agent gets the whole text (including cards posted by apps and workflows, and quoted messages), the author, when it was posted, edited or deleted, its reactions, attached files, pasted images, mentions and its Teams link. For a channel post, it also gets the number of replies and the IDs of the newest ones.
  • From a link. Paste a Teams message link (Copy link on a message in Teams) in the conversation: the agent passes it to the tool, which reads the team, channel, message and thread from the link.
  • Busy channels. All the messages of one listing share a text budget, so a channel with many long messages stays readable: the longest ones are cut shorter, the short ones stay whole, and every cut message carries its note.
  • Both tools are reads. A Teams channel Scope(s) limits the channel tool to the selected channels (a link to another channel is refused) and removes the chat tool.

Microsoft 365: posting a file in a Teams channel

An agent can post a file of its conversation or run in a Teams channel, as the account that authorized the integration: a deck it exported as a PDF, a report, a file a user attached. The tool is send_microsoft_channel_file, and the file is its file_id, the id the tool that produced or received the file returns (export_presentation for a deck).

  • The file is uploaded unchanged into the channel's Files folder (its SharePoint folder), then the message is posted with the file attached, so it opens from the message like a file a person shared. A file of the same name in that folder is replaced, as a new version of it.
  • The post is a new message with an optional text, or a reply in a thread (reply_to_message_id). One file per message, up to 100 MB.
  • The agent gets back the link to the message and the file's SharePoint links.
  • A file that cannot be uploaded posts nothing, and a channel that does not exist (or that the account cannot reach) is reported with nothing uploaded.
  • It is a write: a read-only binding of the integration does not offer it, and a Teams channel Scope(s) limits it to the selected channels. The account must be a member of the team; the delegated permissions ChannelMessage.Send and Files.ReadWrite.All, which the integration requests, cover the post and the upload.

Microsoft 365: deleting Teams messages

An agent can delete a message it posted in Teams, as the account that authorized the integration: a post in a channel, a reply in a thread (delete_microsoft_channel_message, with the thread's first message as parent_message_id for a reply) or a message in a chat (delete_microsoft_chat_message).

  • Teams shows the message as deleted, as when a person deletes their own message. Listing the channel or the chat afterwards shows it as [message deleted].
  • The agent gets back the message ID and the time Teams recorded the deletion. If reading the message back does not show it deleted yet, the result says so instead of reporting a deletion it could not confirm.
  • Only the account's own messages can be deleted. If Microsoft refuses (another person's message, a message that does not exist, a missing permission), the agent gets the error as Microsoft returns it.
  • Both are writes: a read-only binding of the integration does not offer them. A Teams channel Scope(s) limits the channel tool to the selected channels and removes the chat tool.
  • They use the delegated permissions ChannelMessage.ReadWrite (channels) and Chat.ReadWrite (chats), which the integration already requests; editing a message uses the same ones. ChannelMessage.ReadWrite needs admin consent. If editing a channel message already works, deleting one needs no new consent. Otherwise, an administrator adds the permission to the delegated permissions of the integration's app registration in Microsoft Entra ID and grants admin consent, then the integration is re-authorized (Re-authorize on its page). Chat.ReadWrite needs no admin consent.

Microsoft 365: reactions on Teams channel messages

An agent can react with an emoji to a post or a thread reply in a Teams channel, as the account that authorized the integration, and remove that reaction (add_microsoft_channel_message_reaction, remove_microsoft_channel_message_reaction, with the thread's first message as parent_message_id for a reply). For example, it can mark an alert as already handled without anyone opening the thread.

  • Any message of the channel can get a reaction, not only the account's own.
  • The reaction is one emoji, in any skin tone, or one of the Teams reaction names like, heart, laugh, surprised, sad, angry, sent to Microsoft as its emoji. Anything else (text, a custom reaction) is refused before Microsoft is called.
  • If Microsoft refuses (a message that does not exist, a missing permission), the agent gets the error as Microsoft returns it.
  • Both are writes: a read-only binding of the integration does not offer them, and a Teams channel Scope(s) limits them to the selected channels.
  • They use the delegated permission ChannelMessage.Send, which the integration already requests.

Microsoft 365: mentions in Teams messages

An agent can @mention in the messages it posts in Teams, so the people it addresses are notified: an introduction to a channel, an agenda for the team, a question to one person. Typing @channel or a name in the text notifies nobody; the agent passes the mentions to the tool.

  • What can be mentioned. In a channel message, a new post, a reply or an edit (send_microsoft_channel_message, reply_microsoft_channel_message, update_microsoft_channel_message): a person, the channel, the team or one of the team's tags. In a chat message (send_microsoft_chat_message, update_microsoft_chat_message): a person.
  • Which channel and team. A channel mention names the channel the message is posted in, and a team mention the team of that channel. The account posts there, so it is a member; another channel or team is refused, so under a Teams channel Scope(s) a channel mention only ever names a selected channel.
  • Names. The name shown in the message is the real name of the channel, the team, the person or the tag, read from Microsoft unless the agent gives one. A person is named by their email or Microsoft Entra object ID; a tag by its name or ID. Reading a team's tags needs the delegated permission TeamworkTag.Read, which the integration does not request: an administrator adds it to the app registration and grants admin consent, or the agent gives the tag's ID and name.
  • Where they go. Each mention opens the message on a line of its own, unless the agent places it in the text.
  • What the agent gets back. The result says which mentions Teams created; a mention Teams did not keep is reported as such. Listing a channel's messages shows each message's ID and its mentions (what was mentioned and its ID), so the agent can check a message it posted.
  • When Teams refuses. A team's settings can turn off channel and team mentions. If Microsoft refuses the message, the agent gets the error as Microsoft returns it; the message is never posted again without its mentions.

Microsoft 365: Adaptive Cards in Teams messages

An agent can post an Adaptive Card in Teams as the account that authorized the integration: a digest, a status summary or a set of links laid out as a card, in a chat (the account's own self-chat included) or a channel. The bot tools (send_teams_bot_*_card) post as the bot instead, and only where the bot is installed.

  • Which tools. send_microsoft_chat_message, update_microsoft_chat_message, send_microsoft_channel_message, reply_microsoft_channel_message and update_microsoft_channel_message take a card: one Adaptive Card, as its JSON. The message text, when the agent gives one, shows above the card; a card can also be posted alone. Mentions work next to a card.
  • Width. A card posted in a channel spans the full width, unless the card sets its own width. In a chat, Teams fits a card to the message bubble.
  • What a card may hold. A message posted as a person has no bot behind it, so Teams runs only the Action.OpenUrl action. A card with inputs or any other action (Action.Submit, Action.Execute, Action.ShowCard, Action.ToggleVisibility) is refused before anything is posted; such a card goes through the bot tools. A message whose text and card together exceed a Teams message (about 28 KB) is refused too.
  • Editing. An edit sends the whole message again: to keep a card, the agent passes it again.
  • What the agent gets back. For a new post or a reply, the result says whether Teams kept the card, read from the message Teams returns; Teams returns no message for an edit, so the result says the card was sent. Listing the chat or the channel shows the card's text.
  • When Teams refuses. If Microsoft refuses the message, the agent gets the error as Microsoft returns it; the message is never posted again without its card.

Microsoft 365: folders shared in SharePoint and OneDrive

An agent can open a SharePoint or OneDrive folder shared with the account that authorized the integration from its link alone: the Copy link sharing link, or the folder's address in the browser. The folder does not need to be on a site the account is a member of, and no site has to be looked up first. The tool is list_microsoft_folder_by_url.

  • What the agent gets. Every item of the folder with its kind (folder or file), its size, when it last changed, its web address and the URL the other file tools take. A file is read with get_microsoft_file_by_url or kept in the conversation with download_microsoft_file. A subfolder is listed the same way, or by adding its name to the folder's link (the link followed by /Contracts). A large folder is listed page by page, 50 items at a time by default and up to 200.
  • A folder given to the file tools. get_microsoft_file_by_url answers a folder's link with the folder's first items and downloads nothing. download_microsoft_file refuses a folder.
  • Search. Files newly shared with the account can take a while to show in search_microsoft_files; listing their folder shows them at once.
  • Sites. list_microsoft_site_files takes a site by the ID list_microsoft_sharepoint_sites gives, by its address (https://contoso.sharepoint.com/sites/finance), or as contoso.sharepoint.com:/sites/finance. When the account cannot open the site, which is the case when all it holds there is a folder shared with it, the tool says the site is not accessible and points to list_microsoft_folder_by_url.
  • It only reads: a read-only binding of the integration offers it. It uses the delegated permissions Files.Read.All and Sites.Read.All, which the integration already requests.

Microsoft 365: commenting on a Word document

An agent can review a Word document in OneDrive or SharePoint the way a person does: it reads the document, then leaves native Word comments in it, as the account that authorized the integration. Each comment appears on the passage it is about, in Word desktop and Word for the web, under that account's name. The tool is add_microsoft_document_comments; the document is given by its link, or by its path (with the site for a SharePoint library).

  • Where a comment goes. The agent quotes the exact passage the comment is on, as it read it. A passage that appears several times in the document needs its occurrence number (counted from the start of the document); without it, the agent is told how many times it appears and where. A passage the agent misquoted (a different case, typographic quotes, spacing) is refused with the document's exact text to quote instead. A passage that is not in the document is never commented anywhere else.
  • What changes. Only the comments are added: the document's text, formatting and layout are left as they are, and the file gets one new version in its version history. The comments are the document's own comments, so people reply to them, resolve them and delete them in Word as usual.
  • What the agent gets back. For every comment, whether it was placed (with the surrounding text) or refused and why. Comments that could not be placed are left out; the others are saved. If none can be placed, nothing is written.
  • When the document cannot be changed. A document that is checked out, or open for editing by someone else (locked), is refused with nothing written: the agent says so and can try again once it is closed. If the account only has read access to the document, the tool refuses with a clear permission error. If someone saves a new version of the document while the comments are being prepared, nothing is written over it: the agent reads the document again and tries again.
  • It works on .docx files up to 25 MB (not the older .doc format, PDF or other formats). It is a write: a read-only binding of the integration does not offer it. It uses the delegated permissions Files.ReadWrite.All and Sites.ReadWrite.All, which the integration requests.

The agent can also see the comments a document already holds, and take back comments it posted. The same documents, links and limits apply.

  • Listing the comments. list_microsoft_document_comments reads the document and shows every comment with its number, its author, its date, the passage it is on and its text, and marks a comment that answers another one (reply to #N) or that was resolved in Word. The list covers comments made by anyone, in Word or by an agent. It is a read: a read-only binding of the integration offers it.
  • Deleting comments. delete_microsoft_document_comments removes comments by their numbers from the list, or every comment by the connected account at once (all_mine). A deleted comment takes its replies with it, as deleting a thread in Word does. Only the comments are removed: the document's text, formatting and layout are left as they are, and the file gets one new version in its version history. Word shows the remaining comments on their passages as before.
  • Whose comments. By default the agent can only delete comments made by the account that authorized the integration, under that account's name. A comment by anyone else is refused, and the agent is told so; it can remove other people's comments only when explicitly asked to include them (include_others).
  • What the agent gets back. For every number, whether the comment was removed (with its author, its passage and the replies removed with it) or refused and why: a number that is not in the document, or a comment by someone else. If none can be removed, nothing is written. A checked-out, locked or read-only document, and a document someone saved meanwhile, are refused exactly as when adding comments: nothing is written, and the agent says so.

Microsoft 365: formatting an email reply

A draft reply an agent writes in Outlook (create_microsoft_draft_reply, for a reply or a reply to all) stays in the conversation: Outlook shows it in the thread, above the quoted original message, like a reply you write yourself. The agent chooses how the text of the reply is laid out:

  • Plain text (the default). The reply is written line by line, as typed. HTML or Markdown in it is shown as is, tags and symbols included. When a plain-text reply looks like HTML, the agent is told that its tags appear as text.
  • HTML. Headings, tables, lists and links are rendered, as in an email the agent sends with send_microsoft_email, and cleaned the same way: scripts and unsafe links are removed.
  • Markdown. Tables, bold text, headings and links written in Markdown are converted to HTML before the draft is saved.

Microsoft 365: email signatures (Letsignit)

An email an agent writes with the Outlook tools carries the signature of the account that authorized the integration, as an email that person writes in Outlook does.

  • Without a signature integration. A draft reply (create_microsoft_draft_reply) copies the signature of the account's recent sent mail, between the reply and the quoted thread. New emails the agent sends or drafts (send_microsoft_email, create_microsoft_draft_email) carry none: when the person opens a draft in Outlook, their signature add-in signs it as it signs anything they compose.
  • With a Letsignit integration bound to the agent, next to its Microsoft integration, every one of them carries the person's current Letsignit signature: their signature and banner as Letsignit composes them now, read by the mailbox's address. A reply takes its reply variant when Letsignit defines one. It sits where Outlook puts a signature, in the block Outlook writes, so when the person opens a draft, the Letsignit add-in refreshes it there instead of adding a second one. If Letsignit holds no signature for the mailbox, or cannot be reached, a reply falls back on the sent mail's signature and a new email goes unsigned.
  • Setting up Letsignit. Create an API key with the Public API (api) scope in Letsignit (Settings > API keys), add a Letsignit integration with it, and click Test Connection. The Letsignit tools also let an agent read a person's signature and read, create, update the variables of (job title, phone, address, custom variables) or delete a Letsignit user.
  • Signed by the mail server. If your tenant signs mail on the server side (the Letsignit SMTP connector), every outgoing email is already signed in transit: do not bind a Letsignit integration for signing, or emails sent by the agent are signed twice.

The mailbox of an Outlook agent account chooses its own signature source (see Agent accounts).

Google: reviewing a Google Doc

An agent can review a Google Doc the way a person does, as the account that authorized the Google integration: everything it writes appears in the Doc under that account's name, with nothing prefixed.

  • Reading. read_google_doc returns the Doc's text (every tab, with headings, lists and tables) and, apart, its open comment threads: who wrote each one, the passage it is attached to, its replies. Pending suggestions show inline as inserted and deleted. list_google_doc_comments lists every thread, resolved ones included on request.
  • Commenting. add_google_doc_comment posts a comment attached to a passage, highlighted in the Doc like a comment made in the editor. The passage must occur exactly once in the Doc: otherwise nothing is posted, and the agent is told where the passage occurs or what the Doc's exact text is. Without a passage, the comment is on the whole file.
  • Replying and resolving. reply_google_doc_comment answers a thread, and can resolve or reopen it; resolve_google_doc_comment resolves one, with an optional closing message.
  • Changing the text. edit_google_doc replaces text, by default as suggestions the Doc's editors accept or reject. It changes the text directly only when asked to (mode='direct', which needs edit access). Every replacement is counted first: a call whose text matches nothing, or more often than expected, changes nothing, and dry_run shows each match in context without changing anything. A direct edit is applied only to the version of the Doc it counted: if someone edits the Doc in between, nothing is applied.
  • The four writing tools are writes: a read-only binding of the integration offers only the reading ones.

They use the OAuth scopes https://www.googleapis.com/auth/drive (commenting on a file the integration did not create) and https://www.googleapis.com/auth/documents (passages, suggestions and edits), which the integration requests. An integration authorized before it requested them shows a permissions change: re-authorize it (Re-authorize with Google on its page). Until then, a tool that needs a missing scope names it instead of calling Google. The Google Cloud project of the integration's OAuth client must also have the Google Docs API enabled; until it is, read_google_doc falls back on Drive's plain-text export, where [a], [b], ... mark the comments.

Ashby: candidates, applications, interviews and scorecards

An agent connected to Ashby works the recruiting pipeline the way a recruiter reads it in Ashby.

  • Finding people. search_ashby_candidates finds a candidate by name, by email, or both. get_ashby_candidate gives the whole profile (contacts, current role, links, tags, source, custom fields, resume and files) and list_ashby_candidate_applications every job they were considered for.
  • Applications. list_ashby_applications filters by status, job and creation date in Ashby itself, so listing everyone hired for a job (status='Hired', job_id=...) never pages through archived applications. get_ashby_application gives the candidate, the job, the current stage, the source, the archive reason and the dates, including when the candidate was hired (Ashby records the moment they entered the hired stage). list_ashby_application_history gives each stage change: the stage left, the stage entered, when, how long it lasted and who moved it.
  • Scorecards. list_ashby_application_feedback gives every scorecard on an application: who submitted it and when, the form, the interview and stage it was for, and every answer, the ratings and the selected options (such as the overall recommendation) included. submit_ashby_application_feedback checks the answers against the form before submitting: an option can be given by its label, a rating as a number from 1 to 4.
  • Interviews. list_ashby_interviews lists the interviews booked for an application (or for everyone, or only those still to come) with their status, stage, times, interviewers and meeting link. get_ashby_interview opens one. list_ashby_interview_config gives a job's interview plan and its stages, the stage IDs needed to move a candidate. schedule_ashby_interview books an interview; download_ashby_interview_transcript keeps an AI Notetaker transcript in the conversation (Ashby add-on).
  • Jobs and offers. Jobs come with their department, location and hiring team; postings and openings (headcount) can be read and managed. An offer is created in two steps: start_ashby_offer opens it and lists the offer form's fields, create_ashby_offer submits them.
  • Permissions. Each Ashby API key holds read and write permissions per module. Test Connection names the key and the permissions it holds (when the key has API Keys Read), and a tool the key may not use says which permission to grant. Without the key's Allow access to confidential jobs and projects setting, candidates of confidential jobs are invisible to the agent, as if they did not exist.
  • A read-only binding of the integration offers only the reading tools.

Activity

Activity is the change history — when the integration was edited, whether it was tested recently, and whether an issue started after a configuration change.

OpenAPI and Swagger APIs

The OpenAPI / Swagger provider connects any REST API that publishes a Swagger 2.0 or OpenAPI 3.x document, in JSON or YAML. No code is generated: every operation you select becomes one agent tool, and each call is built from the document — the path, query, header, cookie and body parameters, serialized the way the spec declares them.

To create one, choose OpenAPI / Swagger in the catalog, then paste the URL of the raw document (swagger.json, openapi.yaml — not the Swagger UI page) or upload the file, and click Load spec. A spec split across several files ($ref: schemas/pet.yaml) is imported from its URL, where each referenced file is downloaded too, or uploaded as a ZIP archive of all its files. The preview then asks for:

  • The API base URL, pre-filled from the spec's servers. A spec whose server is relative can only fill it in when it was loaded from a URL.
  • A tool name prefix, derived from the API's title, so agents can tell this API's tools apart from others.
  • The authentication, from the security schemes the spec declares: an API key (in a header, the query string or a cookie), a bearer token, HTTP Basic, OAuth2 (authorization code, implicit, device code, client credentials or password), OpenID Connect, a client certificate (mutual TLS), or none. The API key is optional: without one, calls are sent without a credential, and you can add the key later in Configuration.
    • For the authorization code and implicit flows, register <platform URL>/api/oauth/callback as the redirect URI in the API's OAuth app, create the integration, then click Authorize. An implicit token cannot be refreshed: click Authorize again when it expires.
    • With a device code, Authorize shows a code and a link: open the API's sign-in page, enter the code and approve. No redirect URI is needed.
    • Client-credentials and password tokens are requested when tools run and reused until they expire. The password flow takes the username and password of the account the API should act as; its client ID and secret are only needed when the API asks for them.
    • An OpenID Connect scheme is read from its discovery document when the spec loads, and offers the flows its provider supports; its sign-in requests the openid scope, plus offline_access when the provider supports it.
    • A client certificate can be added to any option, under Client certificate: paste or load the PEM certificate, its private key, and the key's passphrase when it is encrypted. It is sent on every call and every token request. An expired certificate is refused, and calls stop with a message saying so; from 30 days before its expiry, the API Spec tab and the integration's overview flag it. To rotate it, have the new certificate issued before the old one expires, then click Replace under Client certificate in the API Spec tab: the next call presents the new one.
  • The operations to expose, grouped by tag. Deprecated operations start switched off, and Read only keeps only the operations that read (GET, HEAD, OPTIONS and QUERY). The pencil next to an operation renames its tool or rewrites its description; agents choose tools by these, so a clear name and description help.

The name and description of the integration can be set on the same page. The description is filled from the spec, and agents read it as context for every tool of the API.

Operations that upload a file become tools too: a multipart file field, or a request body in a file format such as application/octet-stream, an image, a PDF or XML. The agent passes a file available in the conversation, such as a file the user attached, or text it writes, such as a CSV it builds. These operations carry a File badge in the list.

Every HTTP method becomes a tool, including HEAD and OPTIONS, which answer with the response status and headers, and the OpenAPI 3.2 QUERY method and custom methods. TRACE and CONNECT never do: TRACE echoes the request back, credentials included, and CONNECT opens a tunnel instead of calling the API. OpenAPI 3.2 documents are read with their additions too: a querystring parameter is one argument that holds the whole query string, JSON Lines bodies take a list of items, a $self URL is the base of the document's relative links, and tag summaries name the groups of operations.

Some operations cannot become tools, and the preview says why for each: file content in a query, header or path parameter or in a URL-encoded form, TRACE and CONNECT, and definitions that cannot be resolved (a referenced file that cannot be downloaded, for example). An operation the spec marks as public (security: []) is called without the credential. So is an operation the spec places on another server than the base URL (another host, scheme or port), so that a spec cannot send the credential elsewhere; the preview flags these operations.

Calls can reach public hosts and private-network hosts, so an intranet API works. Loopback, link-local and cloud-metadata addresses are always refused, for the spec download, the files it references, and every tool call and token request. Each connection goes to the address that was checked, so a host name that resolves differently a moment later cannot redirect it. Behind an HTTP proxy, which makes the connections itself, each request's URL is checked before it is sent.

An OpenAPI integration adds an API Spec tab to its detail page. It shows where the spec came from, its version and authentication, and lets you change which operations are tools, and their names and descriptions, without importing again. Refresh from URL downloads a URL-sourced spec again: selected operations that disappeared are dropped, new ones stay off until you select them, and the names and descriptions you set are kept. Replace spec loads a different URL, file or archive; the new document must offer an authentication that uses the same kind of credential. The OAuth endpoints and scopes follow the chosen option: the ones it changes are updated, the others keep your edits. The tab also shows the OAuth endpoints and scopes, which you can edit, and the client certificate: its subject, issuer and expiry, with Replace and Remove. Test Connection calls one enabled GET operation that needs no argument.

Agents bind an OpenAPI integration as that specific integration. There is no per-user binding for it, because each OpenAPI integration is a different API. For the members of a shared agent to use its tools, share the integration with their groups.

Admins can switch the whole provider off from the integration catalog, like any other provider.

Read-only and managed nuances

Integrations can have more nuanced edit behavior than other resources. Company-managed integrations are read-only for non-admins, and some suite-level registrations behave like centrally managed records rather than personal connections. Status, tools, and related usage stay visible even when editing is restricted.

Sharing an OAuth integration

An OAuth integration is connected with one person's account: whoever authorized it. You can share it like any other integration - with groups, with individual users, or company-wide by making it company-managed - and once it is shared, everyone it is shared with acts using that connected account. Their agents, assignments and flows use the owner's token, so actions in the external service appear as the owner.

That is the default. When sharing is turned on in Configuration, a notice says so, with one switch below it:

  • Don't share my connected account (off by default; an admin editing someone else's integration sees Don't share the owner's connected account) keeps the integration shared without the owner's account: the owner keeps their connection and is the only one who uses it, and everyone else it is shared with authorizes the integration with their own account (see below). The choice is kept: authorizing the integration again never shares the owner's account. Only the owner or an admin can turn it on or off.
  • Reconnecting a shared integration that shares its account shares the account used to reconnect it; the Authorize button says so. A group-shared or user-shared integration is reconnected by its owner. A company-managed integration can be reconnected by any admin, who then becomes its owner. Turning Don't share my connected account off again shares the owner's account and disconnects everyone's own.
  • Saving asks once: a confirmation names whose account it is, who will act with it and how to avoid it. Confirming shares it; cancelling changes nothing.
  • A member who edits a shared integration without being its owner or an admin cannot share the owner's account: if the owner never shared it, saving a new share shares the integration without it, and the confirmation says so before anything is saved.
  • Stopping sharing - removing every group and user and turning company-managed off - makes the integration personal again: only its owner uses the account until it is shared again.

In a chat, people who cannot see the integration, or whose owner's connected account is not shared with them, use their own account of the same provider instead when they have one; when they do not, a note under the answer says the integration was not used for them and why, and the agent is told too. What carries it - an agent's runs, public link and channels, a flow, a knowledge base import source, a skill's source - acts with its account for that thing's audience, as the next section explains.

The dashboard reminds owners which of their integrations share their connected account, with a shortcut to stop sharing.

Through the API, the choice is the keep_oauth_credentials_on_share field of POST /api/v1/integrations and PUT /api/v1/integrations/{id}: true shares the connected account, false shares the integration without it. A request that shares the integration without the field keeps the account private, as it always did: an account whose sharing was never consented to stays its owner's, and everyone else authorizes their own. An edit that does not change sharing and sends no choice changes nothing.

Shared without the connected account: each person authorizes their own

On an OAuth integration shared with Don't share my connected account:

  • Everyone it is shared with sees a Your account block on the integration's page: Connect your account opens the provider's sign-in for their own account (the integration's OAuth app, the same one for everyone), with its status and Disconnect my account. The integrations list says whether their account is connected.
  • Every run acts with the account of the person it runs for: a chat, the person chatting; an assignment, the person it runs as (else the agent's owner); a flow, its owner; the public widget, event polling and notifications, the agent's owner. Never with someone else's: someone who has not connected theirs gets no tools from the integration, and a note under the answer links to the page where they connect it.
  • The owner connects first and keeps their own connection; the integration reads as connected when theirs is. The people who manage it see who connected an account (names and status, never the account) and can disconnect anyone.
  • A new OAuth app (client ID) disconnects everyone's own account, and someone who can no longer see the integration loses theirs. A skill's private source cannot use such an integration: a skill is shared and refreshed unattended, with no one person whose account it would act with.

This works for every OAuth integration, OpenAPI ones included. Through the API, the choice stays keep_oauth_credentials_on_share (false shares the integration without the account); the integration reports it as credential_mode (shared or per_user). A person disconnects their own account with DELETE /api/v1/integrations/{id}/my-credential; the managers list the connected people with GET /api/v1/integrations/{id}/credentials and disconnect one with DELETE /api/v1/integrations/{id}/credentials/{user_id}.

Sharing a personal credential, everywhere

Any stored credential - an OAuth account, a personal access token, an API key, a bot token, a service-account secret - is used by more than the people an integration is shared with. Everything that carries the integration lends it to its own audience:

  • An agent bound to it: its assignments, its flows, its public web widget, the people who message it on a channel without an account and the platform MCP key all act with the agent's integrations. In a chat, someone the integration is not shared with uses their own account instead, or is told under the answer that it was not used.
  • An assignment that overrides the agent's integrations or listens to an integration's events, for everyone who can use the agent.
  • A flow node, for the flow's audience.
  • A knowledge base import source: its readers see what is synced with it.
  • A skill's private source: it is refreshed with it.
  • The General Assistant's platform bindings, for every user, and a user's own assistant, for that user.

Sharing is never refused. Before a change that lets new people act with someone's credential - sharing an integration, an agent, a knowledge base or a skill, making one company-managed, binding an integration to an agent, an assignment, a flow node, an import source or the General Assistant, enabling an agent's web widget, transferring an owner - one confirmation says whose credential it is ("your GitHub token", "Alice's Jira connected account"), who will be able to use it (with counts, and the public link, anonymous channel users or the MCP key when they apply), through what, what they can do with it (the provider, and the scopes when known) and how to avoid it: Don't share my connected account, switching the agent to per-user integrations, or a company integration. Nothing is asked when nobody new is reached.

The integration's Overview has a Sharing and access section for the people who manage it: every way the credential reaches people, with the reason (shared directly, bound to an agent, an assignment override or trigger, a per-user binding an assignment resolves to the person it runs as, a flow node, an import source, a skill source, the assistants), the audience and a link. An entity you cannot open is named by its owner only. The integration cards show the same thing compactly (Shared - 3 ways), with the breakdown on hover.

The same answers are available to API clients, read-only: GET /api/v1/integrations/{id}/exposure, GET /api/v1/integrations/exposure/summary and POST /api/v1/integrations/exposure/preview (see Sharing and access for every moment you are asked, and the routes every lent resource has).

Scope(s): boundary or guidance

An agent, and each of its assignments, can narrow an integration to specific elements in its Scope(s) card (repositories, channels, CRM object types). The card says which kind of selection it is.

By default every selection is Guidance only: it is given to the agent as instructions ("focus your work on these specific resources"), and its tools can still reach other elements. This is also what every selection made before the choice existed stays.

A selection of one of the four element types below can instead be a hard boundary: turn on Enforce as a boundary next to it, in the agent's or the assignment's Scope(s) card, and save. The card then reads Enforced. The choice is made on each selection, so an agent can enforce its repositories while its Slack channels stay guidance. The Security Audit lists, for information, the selections of these types that are kept as guidance; it does not change the audit's score.

  • Enforced - GitHub repositories. The agent's GitHub tools cannot work on any other repository, in assignments and in chat. A request for another repository is refused with the list of allowed ones, whichever way it names that repository. Repository listings and searches, a team's repositories, sub-issues and project boards show only the selected repositories, and a project card of another repository cannot be changed (draft cards belong to no repository and stay available). The tools that reach repositories without naming one - the raw GraphQL query, repository search, the notification inbox - are not offered, and creating or transferring a repository, changing a team's members and comparing with a branch of another repository are refused. Organization, team, project and user details stay readable.
  • Enforced - Slack channels. The agent's Slack tools cannot read, post to, react in or manage any other conversation, in assignments and in chat; a channel may be named by its ID or its #name. Channel listings and message and file searches show only the selected channels, listing files needs a selected channel, and a file named by its ID is read or deleted only when it is shared in one of them. Direct messages and creating a channel are not offered. Workspace members stay readable. A Slack channel bot the agent posts through is bound by the bot's own publish channels, not by this selection.
  • Enforced - Microsoft Teams channels. The agent's Teams tools cannot read, post to, reply in or list the members of any other channel, in assignments and in chat; a channel meeting's recordings and transcripts are read only in a selected channel (by name or ID), and so is an image pasted in a channel message. The teams-and-channels listing shows the selected channels. Teams chats (1:1 and group) and creating a channel are not offered. The selection applies to Teams only: Outlook mail, calendar, OneDrive, SharePoint, To Do and your own online meetings keep their tools.
  • Enforced - HubSpot CRM object types. The HubSpot tools of an object type that is not selected (contacts, companies, deals, tickets) are not offered, in assignments and in chat, and associations, record deletion, record attachments and the associations a record read includes are refused for any other object type. Marketing email campaigns and the file manager (file search and upload) are not a CRM object type and are not offered; a file is downloaded through the record of a selected type it is attached to. Owners and pipeline definitions stay readable. A custom object is selected and named by its object type ID (2-...).
  • Guidance only - every other element type (GitHub organizations, Jira projects, ...): these have no switch and cannot be enforced. The selection is given to the agent as instructions, but its tools can still reach other elements. Do not rely on it as an access boundary; restrict the integration's own credentials instead.

An assignment refines the agent's selection, and the stricter of the two wins: a type is a boundary for an assignment's runs when the agent or the assignment enforces it. A type the agent enforces is a boundary for every assignment of that agent (the assignment's switch shows it on and locked), and an assignment can enforce a type its agent keeps as guidance. The boundary is then the assignment's refinement of the agent's selection, and one that leaves no valid element (an entry that is not a valid owner/name, or an assignment enforcing repositories its agent does not offer) allows nothing.

The work an agent hands over - to a consulted or transferred agent, or as a background task - stays within the boundaries of the run that handed it over, narrowed further by the other agent's own selection of those types. A selection the delegating run only has as guidance does not follow the work: the other agent keeps working from its own selection, as the prompt it receives says.

What the boundary does not cover

The boundary applies to the GitHub integration's own tools. It does not restrict another route to GitHub the agent may have - an MCP server that exposes GitHub, a custom tool, the code interpreter or the web tools - nor a flow's integration nodes, nor the General Assistant, which has no Scope(s). It does not govern the selected repository's own automation either: a workflow the agent starts runs with that repository's own token and secrets, and GitHub serves the commits of a repository's forks through the repository itself. After a transfer, the conversation continues under the new agent's own selection.

Who receives an integration's events

An assignment with an integration-event trigger listens to the integration its trigger names, or, when it names none, to its agent's first integration of that provider. A flow's integration-event trigger names one too. XTM One reads those events with the integration's credentials and hands them to a run, and checks whether the run's user can see the integration:

  • for an assignment, the user its runs act as: its Run as user, else its owner (the agent's owner);
  • for a flow, the flow's owner.

Seeing the integration means the usual rule: it is theirs, it is shared with them or one of their groups, or it is company-managed and not restricted to an audience. Admins see every integration. A company-managed assignment with neither an owner nor a Run as user keeps the connected-account rule above, as before.

When that user cannot see it, the events are still delivered, as they always were, and never silently: the worker log names the assignment (or the flow and its trigger node) once an hour, and the security audit (GET /api/v1/security-audit, Settings > Security) lists it as a warning. Share the integration with that user, or pick one they can see.

OpenAEV tenants

On a multi-tenant OpenAEV, every OpenAEV tool request acts on one tenant: the one in the integration's Tenant ID field (the tenant's ID in OpenAEV).

  • Left empty (the default), the tenant is chosen the way OpenAEV does for a request that names none: the account's only tenant, or the default tenant when the account belongs to several, it among them. A single-tenant OpenAEV, and an account in the default tenant, need nothing more.
  • Set, every request goes to that tenant. The account must belong to it: otherwise OpenAEV answers TENANT_ACCESS_DENIED, and the error names the tenant the request went to.
  • An account that belongs to several tenants, none of them the default, needs the field: until then creates fail, with an error that says so.

Where to set it:

  • OpenAEV registered with XTM One (the default xtm_one mode): the integration is created and kept up to date by the registration and its page is read-only, except the Tenant ID field, which an administrator edits there. A new registration keeps it. Its token is each user's own, so with the field set, every user of the integration works in that tenant and must belong to it.
  • API-key integration (copilot and dev modes): the field is on the integration form. To work in several tenants, create one integration per tenant and bind each to the agents that work there.

XTM Hub

The XTM Hub integration gives agents the catalog of the XTM Hub, the Filigran ecosystem hub: the ready-to-use resources it publishes for the XTM Platform, namely OpenCTI custom dashboards, custom views, playbooks and integrations (connectors, CSV / TAXII / RSS feeds, live streams, third-party integrations), and OpenAEV scenarios. An agent bound to it can:

  • list the catalogs;
  • search one catalog, or all of them, by text, use case and compatible OpenCTI / OpenAEV version, and for OpenCTI integrations by type, verified status, connector-manager deployment and license;
  • read one resource in full, from its slug or its XTM Hub link;
  • list the newest and the most deployed resources, and the use cases resources are tagged with.

These need no account: keep the authentication mode None. Leave the XTM Hub URL empty to use https://hub.filigran.io, or set the address of another XTM Hub.

With an XTM Hub API token, the agent also works as you in one of your XTM Hub organizations. It can:

  • say whom the token acts as, in which organization, and whether it is read only;
  • list the libraries you reach, private organization libraries included, and search their resources;
  • list the platforms registered with the XTM Hub in that organization;
  • download a resource's file as a file of the conversation or run, which other tools can then use. A downloaded OpenCTI dashboard can be imported into OpenCTI by its file: import_opencti_dashboard takes a file of the conversation as well as JSON, and checks it the same way;
  • with a read and write token, publish a file of the conversation (an OpenCTI dashboard, view or playbook export, an OpenAEV scenario) to a library of yours where you may upload. Each publication is made in your name and stays inactive until someone activates it on the XTM Hub: an agent cannot publish a resource visible at once. Updating or deleting a published resource is done on the XTM Hub.

Once an administrator turns on tool approvals, the download and the publication each wait for your approval; the other XTM Hub tools only read and run without asking.

To set it up, open your profile on the XTM Hub, create a token under API tokens for the organization agents should act in, switch the integration's authentication mode to API Key and paste the token (it starts with xhp_ and the XTM Hub shows it once). A read only token is enough for everything but publishing. The token never signs in, manages tokens or changes who can access what. XTM One sends it only over HTTPS, or to an XTM Hub on the same machine, and only once the XTM Hub says it accepts API tokens. A token belongs to the XTM Hub it was made on: changing the integration's XTM Hub URL, or switching back to None, removes it. A token on a shared integration acts as you for everyone it is shared with, so prefer a read only token there.

Test Connection checks that the address answers as an XTM Hub and lists its catalogs, and with a token names the user and organization it acts as.

Each public result carries the resource's XTM Hub page. Deploying a resource into OpenCTI or OpenAEV is done from that page, with your own XTM Hub session.

Resources are published by the Filigran community. Their names and descriptions reach the agent as untrusted data, never as instructions.

The integration also appears on the home dashboard, next to OpenCTI, OpenAEV and OpenCRQ.

The integration also exists as an import bundle, to distribute it as a package: build it with python -m scripts.build_xtm_hub_bundle from backend/ (it writes xtm-hub-integration-<version>.zip) and import it as an administrator. The bundle creates the custom:xtm-hub provider and an XTM Hub integration pointing at the public XTM Hub. Its tools send the same catalog queries as the built-in integration, each a fixed query whose variables alone the agent chooses, but each search needs the catalog's id from list_xtm_hub_catalogs first and their answers are the XTM Hub's JSON, read with a size limit and handed to the agent as untrusted data, like the built-in tools' answers. Its tools need bundles that support constant values and untrusted answers, which arrived with this integration: on an earlier XTM One the bundle imports, but its tools fail.

Good habits

  • Read the status badge before editing anything.
  • Use Test Connection before assuming the agent is broken.
  • Use the available tools card to understand what the integration really provides.
  • Check scopes and re-authorization warnings when OAuth behavior changes. The platform also marks an OAuth integration as needing re-authorization, and stops refreshing its token, when the provider says the refresh token is revoked or invalid, or rejects the integration's client ID / secret (invalid_client). GitHub and Slack report both inside an otherwise successful answer, and the platform reads them there too: bad_refresh_token (GitHub) and invalid_refresh_token (Slack) for the refresh token, incorrect_client_credentials (GitHub), invalid_client_id and bad_client_secret (Slack) for the client ID / secret. In that last case, update the client ID / secret in Configuration first, then re-authorize: a new consent with the rejected credentials fails the same way. The mark stays until a new authorization succeeds: the platform never retries such an integration on its own, and saving a new client secret, token URL or scopes alone neither reconnects it nor retries the refresh. Saving a new client ID removes the tokens issued to the previous app, so the integration then shows as configured but not yet authorized until you authorize it. A temporary provider failure (a network error, an outage, rate limiting, such as Slack's ratelimited or service_unavailable) never produces this mark; the platform just retries later.
  • Look at Agents Using before editing a shared integration.