Microsoft Outlook
Outlook を Squid に接続し、AI を使用して user の email を index・search します
Outlook Connector の Functionality
Outlook connector を使用すると、Squid AI agent は自然言語で user の Outlook mailbox を read・search できます。各 user は OAuth2 を通じて自身の mailbox を接続します。Squid は delegated per-user access を使用して Microsoft Graph API 経由で mail を読み取るため、agent が閲覧できるのは常に signed-in user の email のみです。
connector は以下をサポートします。
- nested folder を含む user の Outlook mail folder の list 化
- optional cutoff date によりどこまで遡って read するかを制限できる、mail folder(または inbox)の knowledge base への indexing
- agent の ability として公開される、user の index 済み email 全体に対する semantic search
- index 済み folder と各 folder に含まれる email 数の list 化
- knowledge base から folder とその index 済み email を削除
- index 済み folder を最新に保つ automatic background re-sync: 新規 email の index、編集済み email の re-index、削除済み email の remove
Outlook Connector の構成
Squid は OAuth2 と Microsoft Graph API を使用して Outlook に接続します。Microsoft Entra ID(Azure Active Directory)で application を登録し、その application の credential を使用して Squid Console で Outlook connector を追加します。
Microsoft Entra Application の作成
-
Azure Portal に移動し、App registrations を開きます。
-
New registration をクリックし、application に意味のある name を付けます。
-
Supported account types で、mailbox を接続できる user を選択します。
- Microsoft tenant 内の user(work または school account)のみが接続する場合は、Accounts in this organizational directory only を選択します。
- personal account(例:
@outlook.com)を持つ user が接続する場合は、Accounts in any organizational directory and personal Microsoft accounts を選択します。connector は Microsoft のcommonauthority を使用するため、personal account で sign in するにはこの option が必要です。
-
Redirect URI で Web platform を選択し、consent 後に app が redirect する正確な URL を入力します。例:
https://your-app.com/outlook/callback。local development 中は通常http://localhost:5173/outlook/callbackです。この value は、Squid connector で設定する Redirect URL および frontend が consent request で送信する URL と、1 文字単位で一致する必要があります。 -
Register をクリックします。Overview tab で Application (client) ID を控えます。
-
Certificates & secrets に移動し、新しい client secret を作成します。Azure では value が一度しか表示されないため、すぐに Value を copy します。
-
API permissions に移動し、Add a permission > Microsoft Graph > Delegated permissions をクリックして、以下を追加します。
- user の email を read するための
Mail.Read - signed-in user の profile を read するための
User.Read - Microsoft が refresh token を返すための
offline_access(Squid は access token を自動的に refresh します) openidとemail
delegated
Mail.Readは consent 時に各 user が付与できるため、tenant admin consent は optional です。 - user の email を read するための
work account 専用として app を登録し、後から Supported account types を personal account を含むものに変更する場合、Azure は Property api.requestedAccessTokenVersion is invalid で変更を拒否することがあります。personal Microsoft account には v2.0 access token が必要です。application の Manifest を開き、api block 内で "requestedAccessTokenVersion": 2 を設定して保存してから、account type を変更します。
Squid Application に Outlook Connector を追加する
-
Squid Console の Connectors tab に移動します。
-
Available Connectors をクリックし、Outlook connector を見つけ、Add Connector を選択します。
-
以下の configuration を入力します。
Connector ID: code 内で connector を一意に識別する string。connector の call 時に code で渡すため、この ID を控えてください。
Client ID: Entra application の Application (client) ID。
Client Secret: Certificates & secrets で作成した client secret value。
Redirect URL: 上記で Web platform に登録した redirect URI。正確に一致する必要があります。
Application で Outlook Connector を使用する
indexing と listing operation は app の API key で実行されるため、backend code から call する必要があります。frontend は OAuth authorization code を取得した後、connection を完了して mail を index する backend executable を call します。これにより API key を client に置かずに済みます。
No-code Studio
- Squid Console の Studio tab に移動します。
- Create AI Agent をクリックし、
"outlook_agent"、"This agent answers questions about the user's email"などの Agent ID と description を指定します。 - Add Abilities をクリックし、SaaS section まで scroll して、作成した Outlook connector を選択します。ability の詳細はこちら。
- 「user の Outlook email を search するためにこれを call する」など、agent が使用する状況の description を設定します。
agent は、指定 user 用にすでに index 化されている email のみを search できます。まず下記の code flow を使用して mailbox を接続し folder を index してから、agent の実行時に同じ user identifier を指定してください。
Code の基本 Building Block
client package を install します。
npm install @squidcloud/outlook-client
ステップ 1: User を Microsoft に Redirect する
Microsoft consent URL を構築し、user を redirect します。buildOutlookAuthUrl は client package から export された helper です。URL の構築には API key が不要なため、この step は frontend で安全に実行できます。identifier は app 内で user を識別する任意の stable string(たとえば email)です。Squid は token をこの value に紐付けて保存し、indexing と search をこの value に scope します。
import { buildOutlookAuthUrl } from '@squidcloud/outlook-client';
// The redirect URI must exactly match the Web redirect URI registered in Azure
// and the Redirect URL configured on the Squid connector.
const redirectUri = `${window.location.origin}/outlook/callback`;
const consentUrl = buildOutlookAuthUrl({
clientId: 'YOUR_ENTRA_CLIENT_ID',
redirectUri,
state: 'user@example.com', // round-tripped back to your callback as `state`
});
window.location.href = consentUrl;
ステップ 2: Backend で Connection を完了する
Microsoft は、code と渡した state を含めて callback に redirect します。両方を backend executable に送信します。この executable は saveAuthCode を使用して code を token と exchange し、inbox を index します。どちらの operation も app の API key を使用するため、backend で実行する必要があります。
import { executable, SquidService } from '@squidcloud/backend';
import { OutlookClient } from '@squidcloud/outlook-client';
// The Connector ID you set when adding the connector in the Console.
const OUTLOOK_CONNECTOR_ID = 'outlook';
interface ConnectOutlookRequest {
code: string;
identifier: string;
}
export class OutlookService extends SquidService {
// Exchange the Microsoft auth code for tokens, then index the user's inbox.
@executable()
async connectOutlook(request: ConnectOutlookRequest): Promise<void> {
const outlook = new OutlookClient(this.squid, OUTLOOK_CONNECTOR_ID);
// Store the user's tokens under their identifier.
await outlook.saveAuthCode(request.code, request.identifier);
// Index the inbox so an agent can search it. 'inbox' is a well-known folder name.
// Can use { sinceDate: '2024-01-01T00:00:00Z' } to only read mail on or after a cutoff.
const errors = await outlook.indexFolder('inbox', request.identifier);
if (errors.length > 0) {
console.error('Some emails failed to index:', errors);
}
}
}
frontend の callback route は URL から code と state を読み取り、executable を call します。
const url = new URL(window.location.href);
const code = url.searchParams.get('code');
const identifier = url.searchParams.get('state');
if (code && identifier) {
// `squid` comes from your Squid client instance (for example the React SquidContext).
await squid.executeFunction('connectOutlook', { code, identifier });
}
Folder を List 化し、Index 対象を管理する
他の operation 用に追加の backend executable を公開します。それぞれ OutlookClient を構築し、single method を call します。
// List the user's Outlook folders so they can choose which to index.
@executable()
async getOutlookFolders(request: { identifier: string }) {
const outlook = new OutlookClient(this.squid, OUTLOOK_CONNECTOR_ID);
return await outlook.listFolders(request.identifier);
}
// Index a specific folder by id (or a well-known name such as 'inbox').
@executable()
async indexOutlookFolder(request: { folderId: string; identifier: string }) {
const outlook = new OutlookClient(this.squid, OUTLOOK_CONNECTOR_ID);
return await outlook.indexFolder(request.folderId, request.identifier);
}
// List which folders and emails are currently indexed for the user.
@executable()
async getIndexedOutlookItems(request: { identifier: string }) {
const outlook = new OutlookClient(this.squid, OUTLOOK_CONNECTOR_ID);
return await outlook.listIndexedItems(request.identifier);
}
// Remove a folder and all of its indexed emails from the knowledge base.
@executable()
async removeOutlookFolder(request: { folderId: string; identifier: string }) {
const outlook = new OutlookClient(this.squid, OUTLOOK_CONNECTOR_ID);
return await outlook.unindexFolder(request.folderId, request.identifier);
}
AI Agent を通じて Email を検索する
user の mail を index 化した後、Outlook ability を agent に接続して question を尋ねます。agent がその user の email のみを search するように user identifier を設定します。
const agent = this.squid.ai().agent('outlook_agent');
await agent.setAgentOptionInPath('connectedIntegrations', [
{
integrationId: 'outlook',
integrationType: 'outlook',
options: {
identifier: 'user@example.com',
},
},
]);
const answer = await agent.ask('Summarize my most recent emails about the Q3 budget');
agent context で call ごとに identifier を渡すこともでき、default を override します。
const answer = await this.squid
.ai()
.agent('outlook_agent')
.ask('What did Dana say about the launch date?', {
agentContext: { identifier: 'user@example.com' },
});
Core Concept
- Identifier: email など、end user を識別する stable string。Squid は各 user の OAuth token を identifier ごとに保存し、indexing と search を identifier に scope するため、1 つの connector で mail を混在させずに複数 user に対応できます。connect、index、agent call で同じ identifier を使用してください。
- Delegated access: Squid は各 user 固有の access token を使用して、Graph
/meendpoint 経由で mail を読み取ります。agent が閲覧できるのは、実行時に指定された identifier の mail のみです。 - Knowledge base: indexing は、各 email を connector ごとの knowledge base に text context として書き込みます。agent の search ability は、user identifier で filter されたこれらの context に対して semantic search を実行します。
- Background sync: connector は schedule に従って index 済み folder を re-sync します。新規 mail は index 化され、編集済み mail は re-index 化され、削除済み mail は remove され、削除済み folder は cleanup されます。folder を再 index 化する場合、最初の index 時に指定した cutoff date が再利用されます。
Error Handling と Troubleshooting
unauthorized_client: The client does not exist or is not enabled for consumers
personal Microsoft account で sign in していますが、Entra application は work または school account 専用に登録されています。app tenant の account で sign in するか、Supported account types を personal Microsoft account を含む設定に変更してください。Microsoft Entra application の作成を参照してください。
supported account type の変更時に発生する Property api.requestedAccessTokenVersion is invalid
personal Microsoft account には v2.0 access token が必要です。application の Manifest を開き、api block 内に "requestedAccessTokenVersion": 2 を設定して保存してから、account type を変更します。Azure が両方の変更を同時に拒否する場合は、まず token version を保存し、次の保存で account type を変更してください。
Redirect が失敗する、または Microsoft が redirect URI mismatch を report する
redirect URI は、Azure の Web platform redirect URI、Squid connector の Redirect URL、frontend が consent request で送信する URL の 3 か所で同一である必要があります。trailing slash や異なる port も mismatch と見なされます。connector は confidential client token exchange を使用するため、URI が Single-page application ではなく Web platform に登録されていることを確認してください。
Outlook operation の call 時に FUNCTION_NOT_FOUND が発生する
call 対象の app に Outlook connector が追加されていないか、code 内の Connector ID が Console で構成したものと一致していません。Connectors tab に connector があること、および OUTLOOK_CONNECTOR_ID が Connector ID と一致することを確認してください。
Agent が email が index されていないと response する
search の対象は、その identifier 用に index 化済みの mail のみです。最初に mailbox を接続して少なくとも 1 つの folder を index し、agent を同じ identifier で実行していることを確認してください。
ベストプラクティス
- API key は backend に保持します。
saveAuthCode、indexing、listing は backend executable で実行し、frontend からそれらを call してください。client に置くのは consent URL と OAuth redirect のみです。 - large mailbox を index する場合は cutoff date を使用し、必要な範囲までのみ read します。connector は cutoff を保存し、background re-sync でも再利用します。
- connect、index、agent call では、user ごとに一貫した identifier を使用します。identifier の mismatch は、agent が email を見つけられない最も一般的な原因です。
- client secret の expiration 前に rotate し、新しい secret を Console に追加します。Azure では複数の secret を有効にしたままにできるため、downtime なしで rotate できます。
- OAuth token management の詳細については、External Authentication APIを参照してください。