メインコンテンツまでスキップ

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 の作成

  1. Azure Portal に移動し、App registrations を開きます。

  2. New registration をクリックし、application に意味のある name を付けます。

  3. 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 の common authority を使用するため、personal account で sign in するにはこの option が必要です。
  4. Redirect URIWeb 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 文字単位で一致する必要があります。

  5. Register をクリックします。Overview tab で Application (client) ID を控えます。

  6. Certificates & secrets に移動し、新しい client secret を作成します。Azure では value が一度しか表示されないため、すぐに Value を copy します。

  7. 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 します)
    • openidemail

    delegated Mail.Read は consent 時に各 user が付与できるため、tenant admin consent は optional です。

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 を追加する

  1. Squid ConsoleConnectors tab に移動します。

  2. Available Connectors をクリックし、Outlook connector を見つけ、Add Connector を選択します。

  3. 以下の 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

  1. Squid ConsoleStudio tab に移動します。
  2. Create AI Agent をクリックし、"outlook_agent""This agent answers questions about the user's email" などの Agent ID と description を指定します。
  3. Add Abilities をクリックし、SaaS section まで scroll して、作成した Outlook connector を選択します。ability の詳細はこちら
  4. 「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 します。

Client code
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 で実行する必要があります。

Backend code
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 から codestate を読み取り、executable を call します。

Client code
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 します。

Backend code
// 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 を設定します。

Backend code
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 します。

Backend code
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 /me endpoint 経由で 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を参照してください。