注:
API ベースのメッセージ拡張機能では、検索コマンドのみがサポートされます。
API ベースのメッセージ拡張機能は、外部 API を Teams に直接統合し、アプリの使いやすさを高め、シームレスなユーザー エクスペリエンスを提供する、Microsoft Teamsアプリ機能です。 API ベースのメッセージ拡張機能は検索コマンドをサポートしており、Teams 内の外部サービスからデータをフェッチして表示するために使用でき、アプリケーション間の切り替えの必要性を減らすことでワークフローを合理化できます。
注:
エージェントは、より柔軟でインテリジェントで将来に備えたエクスペリエンスを提供します。これにより、より豊かな推論、よりシンプルな開発、進化する Teams および Microsoft 365 プラットフォームとのより適切な連携が可能になります。 エージェントを探索してビルドすることをお勧めします。
詳細については、「Teams での宣言型エージェントのビルドとビルド エージェント」を参照してください。
既存のボットベースのメッセージ拡張機能がある場合は、 エージェントとしても拡張 できます。
作業を開始する前に、次の要件を満たしていることを確認してください。
1. OpenAPI Description (OAD)
OpenAPI Description (OAD) ドキュメントの次のガイドラインに従っていることを確認します。
- OpenAPI バージョン 2.0 および 3.0.x がサポートされています。
- JSON と YAML は、サポートされている形式です。
- 要求本文が存在する場合は、application/Json である必要があります。
-
servers.urlプロパティの HTTPS プロトコル サーバー URL を定義します。 - POST メソッドと GET HTTP メソッドのみがサポートされています。
- OpenAPI Description ドキュメントには、
operationIdが必要です。 - 既定値のない必須パラメーターは 1 つだけ許可されます。
- 既定値の必須パラメーターは省略可能と見なされます。
- ユーザーは、ヘッダーまたは Cookie のパラメーターを入力しないでください。
- 操作には、既定値のない必須のヘッダーパラメーターまたは Cookie パラメーターを含めてはいけません。
- OpenAPI 説明ドキュメントにリモート参照がないことを確認します。
- 要求の配列の構築はサポートされていません。ただし、JSON 要求本文内の入れ子になったオブジェクトはサポートされています。
- Teams では、
oneOf、anyOf、allOf、not(swagger.io) コンストラクトはサポートされていません。
次のコードは、OpenAPI Description ドキュメントの例です。
openapi: 3.0.1
info:
title: OpenTools Plugin
description: A plugin that allows the user to find the most appropriate AI tools for their use cases, with their pricing information.
version: 'v1'
servers:
- url: https://gptplugin.opentools.ai
paths:
/tools:
get:
operationId: searchTools
summary: Search for AI Tools
parameters:
- in: query
name: search
required: true
schema:
type: string
description: Used to search for AI tools by their category based on the keywords. For example, ?search="tool to create music" will give tools that can create music.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/searchToolsResponse'
"400":
description: Search Error
content:
application/json:
schema:
$ref: '#/components/schemas/searchToolsError'
components:
schemas:
searchToolsResponse:
required:
- search
type: object
properties:
tools:
type: array
items:
type: object
properties:
name:
type: string
description: The name of the tool.
opentools_url:
type: string
description: The URL to access the tool.
main_summary:
type: string
description: A summary of what the tool is.
pricing_summary:
type: string
description: A summary of the pricing of the tool.
categories:
type: array
items:
type: string
description: The categories assigned to the tool.
platforms:
type: array
items:
type: string
description: The platforms that this tool is available on.
description: The list of AI tools.
searchToolsError:
type: object
properties:
message:
type: string
description: Message of the error.
詳細については、「OpenAPI 構造体」を参照してください。
2. アプリ マニフェスト
アプリ マニフェストの次のガイドラインに従っていることを確認します。
アプリ マニフェストのバージョンを
1.17に設定します。[
composeExtensions.composeExtensionType] を [apiBased] に設定します。フォルダー内の OpenAPI Description ファイルへの相対パスとして、
composeExtensions.apiSpecificationFileを定義します。 これにより、アプリ マニフェストが API 仕様にリンクされます。応答レンダリング テンプレートへの相対パスとして
apiResponseRenderingTemplateFileを定義します。 これは、API 応答のレンダリングに使用されるテンプレートの場所を指定します。各コマンドには、応答レンダリング テンプレートへのリンクが必要です。 これにより、各コマンドが対応する応答形式に接続されます。
アプリ マニフェストの
Commands.idプロパティは、OpenAPI Description のoperationIdと一致している必要があります。必須パラメーターに既定値がない場合、アプリ マニフェストのコマンド
parameters.nameは、OpenAPI Description ドキュメントのparameters.nameと一致する必要があります。必要なパラメーターがない場合、アプリ マニフェストで
parameters.nameコマンドは、OpenAPI Description の省略可能なparameters.nameと一致する必要があります。各コマンドのパラメーターが、OpenAPI 仕様の操作に対して定義されているパラメーターの名前と正確に一致していることを確認します。
応答レンダリング テンプレートは、API からの応答を変換するために使用されるコマンドごとに定義する必要があります。
完全な説明は 128 文字を超えてはなりません。
{ "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.17/MicrosoftTeams.schema.json", + "manifestVersion": "1.17", "version": "1.0.0", "id": "04805b4b-xxxx-xxxx-xxxx-4dbc1cac8f89", "packageName": "com.microsoft.teams.extension", "developer": { "name": "Teams App, Inc.", "websiteUrl": "https://www.example.com", "privacyUrl": "https://www.example.com/termofuse", "termsOfUseUrl": "https://www.example.com/privacy" }, "icons": { "color": "color.png", "outline": "outline.png" }, "name": { "short": "AI tools", "full": "AI tools" }, "description": { "short": "AI tools", "full": "AI tools" }, "accentColor": "#FFFFFF", "composeExtensions": [ { + "composeExtensionType": "apiBased", + "authorization": { + "authType": "apiSecretServiceAuth ", + "apiSecretServiceAuthConfiguration": { + "apiSecretRegistrationId": "9xxxxxxx-7xxx-4xxx-bxxx-1xxxxxxxxxxx" + } + }, + "apiSpecificationFile": "aitools-openapi.yml", "commands": [ { "id": "searchTools", "type": "query", "context": [ "compose", "commandBox" ], "title": "search for AI tools", "description": "search for AI tools", "parameters": [ { "name": "search", "title": "search query", "description": "e.g. search='tool to create music'" } ], + "apiResponseRenderingTemplateFile": "response-template.json" } ] } ], "validDomains": [] }
パラメーター
| 名前 | 説明 |
|---|---|
composeExtensions.composeExtensionType |
Compose拡張機能の種類。 値を apiBased に更新します。 |
composeExtensions.authorization |
API ベースのメッセージ拡張機能の承認に関する情報 |
composeExtensions.authorization.authType |
可能な承認の種類の列挙型。 サポートされている値は none、apiSecretServiceAuth、microsoftEntra です。 |
composeExtensions.authorization.apiSecretServiceAuthConfiguration |
サービス認証を実行するために必要なオブジェクトキャプチャの詳細。認証の種類が apiSecretServiceAuthされている場合にのみ適用されます。 |
composeExtensions.authorization.apiSecretServiceAuthConfiguration.apiSecretRegistrationId |
開発者が開発者ポータルを介して API キーを送信したときに返される登録 ID。 |
composeExtensions.apiSpecificationFile |
アプリ パッケージ内の OpenAPI Description ファイルを参照します。 型が apiBasedされている場合に含めます。 |
composeExtensions.commands.id |
検索コマンドに割り当てる一意の ID。 ユーザー要求には、この ID が含まれています。 ID は、OpenAPI Description で使用可能な OperationId と一致している必要があります。 |
composeExtensions.commands.context |
メッセージ拡張のエントリ ポイントが定義されている配列。 既定値は compose と commandBoxです。 |
composeExtensions.commands.parameters |
コマンドのパラメーターの静的リストを定義します。 名前は、OpenAPI Description の parameters.name にマップする必要があります。 要求本文スキーマでプロパティを参照している場合、名前は properties.name またはクエリ パラメーターにマップする必要があります。 |
composeExtensions.commands.apiResponseRenderingTemplateFile |
開発者の API からアダプティブ カード応答への JSON 応答の書式設定に使用されるテンプレート。 [必須] |
詳細については、「 composeExtensions」を参照してください。
3. 応答レンダリング テンプレート
-
$schemaプロパティでスキーマ参照 URL を定義して、テンプレートの構造を確立します。 -
responseLayoutでサポートされている値はlistとgridであり、応答がどのように視覚的に表示されるかを決定します。 - 配列の場合、またはアダプティブ カードのデータがルート オブジェクトではない場合は、
jsonPathをお勧めします。 たとえば、データがproductDetailsの下に入れ子になっている場合、JSON パスはproductDetailsされます。 -
jsonPathを、API 応答の関連データまたは配列へのパスとして定義します。 パスが配列を指している場合、配列内の各エントリはアダプティブ カード テンプレートとバインドされ、個別の結果として返されます。 [省略可能] - 応答 レンダリング テンプレートを検証するためのサンプル応答を取得します。 これは、テンプレートが期待どおりに動作することを確認するためのテストとして機能します。
- Fiddler や Postman などのツールを使用して API を呼び出し、要求と応答が有効であることを確認します。 この手順は、API が正しく機能していることをトラブルシューティングして確認するために重要です。
- アダプティブ カード Designerを使用して、API 応答を応答レンダリング テンプレートにバインドし、アダプティブ カードをプレビューできます。 カード ペイロード エディターにテンプレートを挿入し、サンプル データ エディターにサンプル応答エントリを挿入します。
次のコードは、応答レンダリング テンプレートの例です。
応答レンダリング テンプレートの例
{
"version": "1.0",
"jsonPath": "repairs",
"responseLayout": "grid",
"responseCardTemplate": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Title: ${if(title, title, 'N/A')}",
"wrap": true
},
{
"type": "TextBlock",
"text": "Description: ${if(description, description, 'N/A')}",
"wrap": true
},
{
"type": "TextBlock",
"text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
"wrap": true
},
{
"type": "Image",
"url": "${image}",
"size": "Medium",
"$when": "${image != null}"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "${if(image, image, '')}",
"size": "Medium"
}
]
}
]
},
{
"type": "FactSet",
"facts": [
{
"title": "Repair ID:",
"value": "${if(id, id, 'N/A')}"
},
{
"title": "Date:",
"value": "${if(date, date, 'N/A')}"
}
]
}
]
}
]
},
"previewCardTemplate": {
"title": "Title: ${if(title, title, 'N/A')}",
"subtitle": "Description: ${if(description, description, 'N/A')}",
"text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
"image": {
"url": "${image}",
"$when": "${image != null}"
}
}
}
プレビュー カード
拡張アダプティブ カード
パラメーター
| プロパティ | 型 | 説明 | 必須 |
|---|---|---|---|
version |
string |
現在の応答レンダリング テンプレートのスキーマ バージョン。 | はい |
jsonPath |
string |
responseCardTemplate と previewCardTemplate を適用する必要がある結果の関連セクションへのパス。 設定されていない場合、ルート オブジェクトは関連セクションとして扱われます。 関連するセクションが配列の場合、各エントリは responseCardTemplate と previewCardTemplate にマップされます。 | 不要 |
responseLayout |
responseLayoutType |
メッセージ拡張ポップアップの結果のレイアウトを指定します。 サポートされている型は、 list と gridです。 |
はい |
responseCardTemplate |
adaptiveCardTemplate |
結果エントリからアダプティブ カードを作成するためのテンプレート。 | はい |
previewCardTemplate |
previewCardTemplate |
結果エントリからプレビュー カードを作成するためのテンプレート。 結果のプレビュー カードは、メッセージ拡張機能のポップアップ メニューに表示されます。 | はい |
JSON パス
JSON パスは省略可能ですが、配列に使用することも、アダプティブ カードのデータとして使用するオブジェクトがルート オブジェクトではない場合にも使用できます。 JSON パスは、Newtonsoft によって定義された形式に従う必要があります。 JSON パスが配列を指している場合、その配列内の各エントリはアダプティブ カード テンプレートにバインドされ、個別の結果として返されます。
例たとえば、製品の一覧に対して以下の JSON があり、エントリごとにカード結果を作成するとします。
{
"version": "1.0",
"title": "All Products",
"warehouse": {
"products": [
...
]
}
}
ご覧のとおり、結果の配列は "products" の下にあり、これは "warehouse" の下に入れ子になっているため、JSON パスは "warehouse.products" になります。
アダプティブ カード Designerを使用して、カード ペイロード エディターにテンプレートを挿入してアダプティブ カードをプレビューします。 配列またはオブジェクトのサンプル応答エントリを取得し、サンプル データ エディターに挿入します。 カードが適切にレンダリングされ、好みに合っていることを確認します。
スキーマ マッピング
OpenAPI Description ドキュメントのプロパティは、次のようにアダプティブ カード テンプレートにマップされます。
string、number、integer、boolean型は TextBlock に変換されます。例
ソース スキーマ:
string、number、integer、およびbooleanname: type: string example: doggieターゲット スキーマ:
Textblock{ "type": "TextBlock", "text": "name: ${if(name, name, 'N/A')}", "wrap": true }
array: 配列はアダプティブ カード内のコンテナーに変換されます。例
ソース スキーマ:
arraytype: array items: required: - name type: object properties: id: type: integer category: type: object properties: name: type: stringターゲット スキーマ:
Container{ "type": "Container", "$data": "${$root}", "items": [ { "type": "TextBlock", "text": "id: ${if(id, id, 'N/A')}", "wrap": true }, { "type": "TextBlock", "text": "category.name: ${if(category.name, category.name, 'N/A')}", "wrap": true } ] }
object: オブジェクトがアダプティブ カードの入れ子になったプロパティに変換されます。例
ソース スキーマ:
objectcomponents: schemas: Pet: category: type: object properties: id: type: integer name: type: stringターゲット スキーマ: アダプティブ カードの入れ子になったプロパティ
{ "type": "TextBlock", "text": "category.id: ${if(category.id, category.id, 'N/A')}", "wrap": true }, { "type": "TextBlock", "text": "category.name: ${if(category.name, category.name, 'N/A')}", "wrap": true }
image: プロパティがイメージ URL の場合は、アダプティブ カードの Image 要素に変換されます。例
ソース スキーマ:
imageimage: type: string format: uri description: The URL of the image of the item to be repairedターゲット スキーマ:
"Image"{ "type": "Image", "url": "${image}", "$when": "${image != null}" }
Api ベースのメッセージ拡張機能は、開発者ポータル for Teams、Microsoft 365 Agents Toolkit (以前は Teams Toolkit) for Visual Studio Code、コマンド ライン インターフェイス (CLI)、または Visual Studio を使用して作成できます。
開発者ポータルを使用して API ベースのメッセージ拡張機能を作成するには、次の手順に従います。
開発者ポータルに移動します。
[アプリ] に移動します。
[ + 新しいアプリ] を選択します。
アプリの名前を入力し、 マニフェスト バージョン を パブリック開発者プレビュー (devPreview) として選択します。
[追加] を選択します。
左側のウィンドウの [ 構成] で、次の 基本情報を更新します。
- フル ネーム
- 簡潔な説明
- 詳しい説明
- 開発者または会社名
- Web サイト (有効な HTTPS URL である必要があります)
- プライバシー ポリシー
- 使用条件
[保存] を選択します。
[ アプリ機能] を選択します。
[ メッセージ拡張機能] を選択します。
[ メッセージ拡張機能の種類] で、[API] を選択 します。
- Bot メッセージ拡張機能を読み取る免責事項 がユーザーによって既に使用されている場合。メッセージ拡張機能の種類を API に変更しますか?、 はい、変更を選択します。
[ OpenAPI spec]\(OpenAPI 仕様\) で、[ 今すぐアップロード] を選択します。
JSON または YAML 形式で OpenAPI Description ドキュメントを選択し、[ 開く] を選択します。
[保存] を選択します。 メッセージ API 仕様が正常に保存されたポップアップが表示されます。
[ 入手] を選択します。
コマンドの追加
注:
API からビルドされたメッセージ拡張機能は、1 つのパラメーターのみをサポートします。
コマンドとパラメーターをメッセージ拡張機能に追加して、コマンドを追加できます。
[ メッセージ拡張機能の種類] で、[ 追加] を選択します。
[ コマンドの追加] ポップアップが表示され、OpenAPI Description ドキュメントから使用可能なすべての API の一覧が表示されます。
一覧から API を選択し、[ 次へ] を選択します。
[ 応答テンプレート] で、[ 今すぐアップロード] を選択します。
注:
複数の API がある場合は、各 API のアダプティブ カード応答テンプレートをアップロードしてください。
JSON 形式のアダプティブ カード応答テンプレート ファイルを選択し、[ 開く] を選択します。
アダプティブ カード テンプレートから次の属性が自動的に更新されます。
- コマンドの種類
- コマンド ID
- コマンドのタイトル
- パラメーター名
- パラメータの説明
[ 詳細] で、 コマンドの説明を更新します。
Microsoft 365 Copilotでトリガーを使用してコマンドを起動する場合は、[ユーザーが拡張機能を開いたときにこのコマンドを自動的に実行する] トグルをオンにします。
[追加] を選択します。 コマンドが正常に追加されました。
[保存] を選択します。
[ 認証と承認] で、次のいずれかのオプションを選択します。
- 認証なし (推奨されません)
- API キー
- OAuth
API ベースのメッセージ拡張機能が作成されます。
開発者ポータルで作成された API ベースのメッセージ拡張機能をテストするには、次の方法を使用します。
Teams でのプレビュー: メッセージ拡張機能を開き、右上隅 にある [Teams でプレビュー ] を選択します。 Teams にリダイレクトされ、アプリを Teams に追加してアプリをプレビューできます。
アプリ パッケージのダウンロード: メッセージ拡張機能ページで、左側のウィンドウで [ アプリ パッケージ ] を選択し、ウィンドウの左上隅にある [ アプリ パッケージのダウンロード] を選択します。 アプリ パッケージは、.zip ファイル内のローカル コンピューターにダウンロードされます。 アプリ パッケージをチームにアップロードし、メッセージ拡張機能をテストできます。
複数パラメーター
複数パラメーターを使用すると、API ベースのメッセージ拡張機能でクエリ コマンドに対して複数の入力型を使用できます。 たとえば、ジャンル、レーティング、ステータス、日付でアニメを検索できます。
マニフェスト内のパラメーターの入力型、タイトル、説明、および必須フィールドを指定できます。
- パラメーター フィールドの
isRequiredプロパティは、パラメーターがクエリ コマンドに必須かどうかを示します。 - アプリ マニフェストの
parametersフィールドのnameプロパティは、対応するパラメーターの OpenAPI Description ドキュメントのidフィールドと一致する必要があります。
例
"composeExtensions": [
{
"composeExtensionType": "apiBased",
"apiSpecificationFile": "apiSpecificationFiles/openapi.json",
"commands": [
{
"context": [
"compose"
],
"type": "query",
"title": "Search Animes",
"id": "getAnimeSearch",
"parameters": [
{
"name": "q",
"title": "Search Query",
"description": "The search query",
"isRequired": true
},
{
"name": "type",
"inputType": "choiceset",
"title": "Type",
"description": "Available anime types",
"choices": [
{
"title": "TV",
"value": "tv"
},
{
"title": "OVA",
"value": "ova"
},
{
"title": "Movie",
"value": "movie"
},
{
"title": "Special",
"value": "special"
},
{
"title": "ONA",
"value": "ona"
},
{
"title": "Music",
"value": "music"
}
]
},
{
"name": "status",
"inputType": "choiceset",
"title": "Status",
"description": "Available airing statuses",
"choices": [
{
"title": "Airing",
"value": "airing"
},
{
"title": "Completed",
"value": "complete"
},
{
"title": "Upcoming",
"value": "upcoming"
}
]
},
{
"name": "rating",
"inputType": "choiceset",
"title": "Rating",
"description": "Available ratings",
"choices": [
{
"title": "G",
"value": "g"
},
{
"title": "PG",
"value": "pg"
},
{
"title": "PG-13",
"value": "pg13"
},
{
"title": "R",
"value": "r17"
},
{
"title": "R+",
"value": "r"
},
{
"title": "Rx",
"value": "rx"
}
]
}
],
"description": "Search animes",
"apiResponseRenderingTemplateFile": "response_json/getAnimeSearch.json"
},
{
"context": [
"compose"
],
"type": "query",
"title": "Search mangas",
"id": "getMangaSearch",
"parameters": [
{
"name": "q",
"title": "Search Query",
"description": "The search query",
"isRequired": true
},
{
"name": "type",
"inputType": "choiceset",
"title": "Type",
"description": "Available manga types",
"choices": [
{
"title": "Manga",
"value": "manga"
},
{
"title": "Novel",
"value": "novel"
},
{
"title": "Light Novel",
"value": "lightnovel"
},
{
"title": "One Shot",
"value": "oneshot"
},
{
"title": "Doujin",
"value": "doujin"
},
{
"title": "Manhwa",
"value": "manhwa"
},
{
"title": "Manhua",
"value": "manhua"
}
]
},
{
"name": "status",
"inputType": "choiceset",
"title": "Status",
"description": "Available manga statuses",
"choices": [
{
"title": "Publishing",
"value": "publishing"
},
{
"title": "Complete",
"value": "complete"
},
{
"title": "Hiatus",
"value": "hiatus"
},
{
"title": "Discontinued",
"value": "discontinued"
},
{
"title": "Upcoming",
"value": "upcoming"
}
]
},
{
"name": "start_date",
"title": "Start Date",
"description": "Start date of the manga",
"inputType": "date"
},
{
"name": "end_date",
"title": "End Date",
"description": "End date of the manga",
"inputType": "date"
}
],
ステップ バイ ステップのガイド
API ベースのメッセージ拡張機能を構築するには、「 API ベースのメッセージ拡張機能をビルドする」を参照してください。
関連項目
Platform Docs