Microsoft Outlook
Outlook を Squid に接続し、AI でユーザーのメールを index・検索する
Outlook connector の機能
Outlook connector を使用すると、Squid AI agents は自然言語を使ってユーザーの Outlook mailbox を読み取り、検索できます。各ユーザーは OAuth2 経由で自分の mailbox を接続し、Squid は delegated per-user access を使用して Microsoft Graph API 経由でメールを読み取るため、agent が参照できるのは常にサインイン中のユーザーのメールだけです。
connector は以下をサポートします。
- ネストされた folders を含む、ユーザーの Outlook mail folders の一覧表示
- mail folder(または inbox)を knowledge base に index。読み取り対象を過去の一定期間に制限する optional cutoff date に対応
- ユーザーの indexed email 全体に対する semantic search。agent の ability として公開
- どの folders が indexed で、それぞれに何件の emails が含まれるかの一覧表示
- folder とその indexed email を knowledge base から削除
- 自動 background re-sync により、indexed folders を最新の状態に維持: 新しい email は index され、編集された email は再 index され、削除された email は削除されます
Outlook connector の設定
Squid は OAuth2 と Microsoft Graph API を使用して Outlook に接続します。Microsoft Entra ID(Azure Active Directory)で application を登録し、その application の credentials を使用して Squid Console に Outlook connector を追加します。
Microsoft Entra application の作成
-
Azure Portal に移動し、App registrations に移動します。
-
New registration をクリックし、application にわかりやすい名前を付けます。
-
Supported account types で、誰が自分の mailbox を接続できるかを選択します。
- Microsoft tenant 内のユーザー(work or school accounts)のみが接続する場合は、Accounts in this organizational directory only を選択します。
- personal accounts(例:
@outlook.com)を持つユーザーが接続する場合は、Accounts in any organizational directory and personal Microsoft accounts を選択します。connector は Microsoftcommonauthority を使用するため、personal accounts がサインインするにはこの option が必要です。
-
Redirect URI で Web platform を選択し、consent 後に app が redirect する正確な URL を入力します。例:
https://your-app.com/outlook/callback。local development 中は通常http://localhost:5173/outlook/callbackです。この値は、Squid connector に設定する Redirect URL および frontend が consent request で送信する URL と、一文字単位で一致している必要があります。 -
Register をクリックします。Overview tab で Application (client) ID を控えます。
-
Certificates & secrets に移動し、新しい client secret を作成して、その Value をすぐにコピーします。Azure では値は一度しか表示されないためです。
-
API permissions に移動し、Add a permission > Microsoft Graph > Delegated permissions をクリックして、以下を追加します。
- ユーザーの email を読み取るための
Mail.Read - サインイン中のユーザーの profile を読み取るための
User.Read - Microsoft が refresh token を返すようにするための
offline_access(Squid は access tokens を自動的に refresh します) openidとemail
Delegated
Mail.Readは各ユーザーが consent 時に付与できるため、tenant admin consent は optional です。 - ユーザーの email を読み取るための
work accounts のみを対象として app を登録した後、Supported account types を personal accounts を含むように変更すると、Azure が Property api.requestedAccessTokenVersion is invalid で変更を拒否する場合があります。personal Microsoft accounts には v2.0 access tokens が必要です。application の Manifest を開き、api block 内で "requestedAccessTokenVersion": 2 を設定して保存し、その後 account types を変更してください。
Squid application への Outlook connector の追加
-
Squid Console の Connectors tab に移動します。
-
Available Connectors をクリックし、Outlook connector を見つけて Add Connector を選択します。
-
次の configuration を入力します。
Connector ID: code 内で connector を一意に識別する string。この ID は、code から connector を呼び出すときに渡すため控えておいてください。
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 operations は app の API key を使用して実行されるため、backend code から呼び出す必要があります。frontend は OAuth authorization code を取得し、その後、connection を完了して mail を index する backend executable を呼び出します。これにより、API key を client に置かずに済みます。
No-code Studio
- Squid Console の Studio tab に移動します。
- Create AI Agent をクリックし、Agent ID と description を入力します。例: "outlook-agent" と "This agent answers questions about the user's email"。
- Add Abilities をクリックし、SaaS section まで scroll して、作成した Outlook connector を選択します。abilities の詳細はこちら。
- agent がそれをいつ使用すべきかの description を入力します。例: "Call this to search the user's Outlook email."
agent は、特定のユーザーについてすでに indexed された email のみを検索できます。以下の code flow を使用して、まず mailbox を接続し folder を index してから、agent 実行時に同じ user identifier を指定してください。
code の基本 building blocks
client package を install します。
npm install @squidcloud/outlook-client
Step 1: ユーザーを Microsoft に redirect する
Microsoft consent URL を構築し、ユーザーを redirect します。buildOutlookAuthUrl は client package から export される helper です。URL の構築に API key は不要なので、この step は frontend で安全に実行できます。identifier は、app 内でユーザーを識別する任意の stable string(例: ユーザーの email)です。Squid はその identifier の下に tokens を保存し、indexing と search をその identifier に 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;
Step 2: backend で connection を完了する
Microsoft は、code と渡された state を付けて callback に redirect します。その両方を backend executable に送信し、saveAuthCode で code を tokens に交換してから 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 を呼び出します。
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 });
}
folders の listing と indexed 対象の管理
その他の operations 用に追加の backend executables を公開します。それぞれが OutlookClient を構築し、単一の method を呼び出します。
// 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 を検索する
ユーザーの mail が indexed になったら、Outlook ability を agent に接続して質問します。agent がそのユーザーの email のみを検索するように 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 concepts
- Identifier: email など、end user を識別する stable string。Squid は各ユーザーの OAuth tokens をその identifier の下に保存し、indexing と search をそこに scope するため、1 つの connector で複数のユーザーに対応しても mail が混ざることはありません。connect、index、agent calls 全体で同じ identifier を使用してください。
- Delegated access: Squid は、各ユーザー自身の access token を使用して Graph
/meendpoints 経由で mail を読み取ります。agent が参照できるのは、実行対象の identifier の mail のみです。 - Knowledge base: indexing は、各 email を per-connector knowledge base 内の text context として書き込みます。agent の search ability は、これらの contexts に対して semantic search を実行し、ユーザーの identifier で filter します。
- Background sync: connector は schedule に従って indexed folders を再 sync します。新しい mail は index され、編集された mail は再 index され、削除された mail は削除され、削除された 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 でサインインしましたが、Entra application は work or school accounts のみを対象として登録されています。app の tenant の account でサインインするか、Supported account types を personal Microsoft accounts を含むように変更してください。Microsoft Entra application の作成 を参照してください。
Property api.requestedAccessTokenVersion is invalid when changing supported account types
personal Microsoft accounts には v2.0 access tokens が必要です。application の Manifest を開き、api block 内で "requestedAccessTokenVersion": 2 を設定して保存し、その後 account types を変更してください。Azure が両方の変更を同時に行うことをまだ拒否する場合は、まず token version を保存し、2 回目の保存で account types を変更してください。
redirect が失敗する、または Microsoft が redirect URI mismatch を報告する redirect URI は、Azure の Web platform redirect URI、Squid connector の Redirect URL、frontend が consent request で送信する URL の 3 か所で完全に一致している必要があります。末尾の slash や異なる port も mismatch と見なされます。connector は confidential client token exchange を使用するため、URI が Single-page application ではなく Web platform の下に登録されていることを確認してください。
Outlook operation の呼び出し時に FUNCTION_NOT_FOUND が発生する
Outlook connector が呼び出し先の app に追加されていないか、code 内の Connector ID が Console で設定されたものと一致していません。connector が Connectors tab の下に存在すること、および OUTLOOK_CONNECTOR_ID がその Connector ID と一致していることを確認してください。
agent が emails are indexed されていないと応答する search は、その identifier に対して indexed された mail のみを対象とします。まず mailbox を接続し、少なくとも 1 つの folder を index してください。また、agent が index 時と同じ identifier で実行されていることを確認してください。
Best practices
- API key は backend に保持してください。
saveAuthCode、indexing、listing は backend executables で実行し、frontend からそれらを呼び出すようにします。client に置くべきなのは consent URL と OAuth redirect のみです。 - 大きな mailboxes を indexing する場合は cutoff date を使用し、必要な範囲までだけ読み取るようにしてください。connector は cutoff を保存し、background re-syncs 中に再利用します。
- connect、index、agent calls 全体で、ユーザーごとに一貫した identifier を使用してください。mismatch は、agent が email を見つけられない最も一般的な原因です。
- client secrets は有効期限が切れる前に rotate し、新しい secret を Console に追加してください。Azure では複数の secret を active にしておけるため、downtime なしで rotate できます。
- OAuth token management の詳細については、External Authentication API を参照してください。