Teamsアプリのmanifest.jsonは、アプリの機能やURLなどをTeamsへ伝える設定ファイルです。
一般的なJSONパーサーで読み込めても、Teams固有の必須項目、データ型、値の形式に適合するとは限りません。
そこで、プレースホルダー(後から実際の値に置き換える仮の文字列)を含むmanifest.template.jsonから検証用ファイルを生成し、Microsoft 365 Agents Toolkit CLI(以下、Agents Toolkit CLI)のatk validateで検証しました。
本記事では、JSON構文確認からスキーマ検証までの手順と、検証結果の読み方を紹介します。
Teamsアプリマニフェストで確認する4つの段階
今回の確認は、次の4段階のうち1と2を対象にします。
ここでいう「スキーマ」と「検証ルール」には、次の違いがあります。
- スキーマ(Schema):
manifest.jsonに必要な項目、データ型、値の形式などを定めたルール - 検証ルール(Validation Rules):スキーマによる確認とは別に、Agents Toolkitがアプリに対して行う追加のチェック
本記事では、Agents Toolkit CLIの出力に合わせて、以降は「スキーマ」と「検証ルール」と表記します。
| 確認 | 主に分かること | これだけでは分からないこと |
|---|---|---|
| 1. JSON構文確認 | 括弧、カンマ、引用符などがJSONとして正しいか | Teams固有の必須項目や値の形式に適合するか |
| 2. スキーマ/検証ルールの確認 | Teamsアプリマニフェストのスキーマと、 Agents Toolkitが適用する追加の検証ルールに適合するか | ZIPの構成やアイコンが適切か、Teams上で動作するか |
| 3. アプリパッケージ検証 | ZIPの構成、manifest.json、アイコンなどがアプリパッケージの要件に適合するか | 実URLへの到達性、画面表示、認証などが正常に動作するか |
| 4. Teams上での動作・配布確認 | アプリをアップロードでき、タブの表示、URL到達性、iframe、CSP、TeamsJS、認証などが正常に動作するか | 別のテナントでも同じポリシーや配布条件で利用できるか |
Teamsアプリマニフェストの検証範囲と環境
今回検証するのは、検証用に生成したmanifest.jsonのJSON構文、スキーマ、検証ルールです。
正式なApp IDと実URLを入れた完成版マニフェスト、アイコンを含むZIP、Teamsへのアップロード、画面表示、認証、配布条件は対象外です。
| 項目 | 内容 |
|---|---|
| 実測日 | 2026年9月8日 |
| OS/シェル | macOS 26.6/zsh 5.9 |
| Agents Toolkit CLI | 1.1.16 |
| Node.js | v26.8.1 |
| Teamsアプリマニフェストのスキーマ | 1.29 |
スキーマやCLIは更新されるため、実行時点の公式情報とローカルのヘルプも確認してください。
Microsoft 365 Agents Toolkit CLIを準備する
Node.jsとnpmを準備し、Agents Toolkit CLIをインストールします。
npm install -g @microsoft/m365agentstoolkit-cli
atk --version
atk validate -h上記のインストールコマンドは、実行時点でnpmから取得できるバージョンをインストールします。
この記事の実測ではバージョン1.1.16を使用しました。厳密に同じ結果を再現したい場合は、利用するバージョンをそろえてください。
CLI 1.1.16でマニフェストを指定するオプションは--manifest-fileでした。
現行のCLIリファレンスにも--manifest-fileと記載されていますが、別のMicrosoft Learnページには--manifest-pathという表記も残っています。バージョンによって使えるオプションが異なる可能性があるため、実行環境のatk validate -hを優先します。
検証用のTeamsアプリマニフェストを生成する
teams_tab/manifest/manifest.template.jsonがあるサンプルプロジェクトへ移動し、入出力先を設定します。
cd /path/to/sample-teams-app
PROJECT_ROOT="$(pwd)"
TEMPLATE="$PROJECT_ROOT/teams_tab/manifest/manifest.template.json"
RENDERED_MANIFEST="$PROJECT_ROOT/validation-evidence/rendered-manifest.json"
mkdir -p "$(dirname "$RENDERED_MANIFEST")"validation-evidenceをリポジトリ内に作る場合は、検証用App IDを含む生成物を誤ってコミットしないよう、除外設定も確認してください。
続いてNode.jsで元ファイルを解析し、URLホストと全ゼロGUIDを検証用の値へ置換します。
以下のコードでは、公開用にプレースホルダー名をAPP_HOSTなどへ一般化しています。手元のテンプレートに合わせてreplacementsの左側を変更してください。
.invalidは、無効なドメイン名の例示に使うため予約されているトップレベルドメインです。ここでは値の形式を満たすために使用しており、実URLへの到達性は確認しません。
TEST_APP_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"
node -e '
const fs = require("fs");
const [template, output, appId] = process.argv.slice(1);
let content = fs.readFileSync(template, "utf8");
// 置換前のファイルがJSONとして読めることを確認する
JSON.parse(content);
const replacements = {
"{{APP_HOST}}": "teams-tab-schema-test.invalid",
"{{DEVELOPER_WEBSITE_HOST}}": "developer-schema-test.invalid",
"{{PRIVACY_POLICY_HOST}}": "privacy-schema-test.invalid",
"{{TERMS_OF_USE_HOST}}": "terms-schema-test.invalid",
"00000000-0000-0000-0000-000000000000": appId
};
for (const [from, to] of Object.entries(replacements)) {
if (!content.includes(from)) {
throw new Error(`置換対象が見つかりません: ${from}`);
}
content = content.split(from).join(to);
}
fs.writeFileSync(output, content, "utf8");
' "$TEMPLATE" "$RENDERED_MANIFEST" "$TEST_APP_ID"置換対象の存在確認を入れているため、テンプレートの変更やプレースホルダー名のタイプミスも検出できます。
ここで使用した値は検証専用です。正式版には、承認されたApp IDと実URLを設定してください。
生成したmanifest.jsonを確認する
生成後のJSON構文と、未置換の値がないことを確認します。
node -e '
const fs = require("fs");
const content = fs.readFileSync(process.argv[1], "utf8");
JSON.parse(content);
const tokens = [...new Set(content.match(/\{\{[^{}]+\}\}/g) || [])];
if (tokens.length) {
throw new Error(`未置換トークン: ${tokens.join(", ")}`);
}
if (content.includes("00000000-0000-0000-0000-000000000000")) {
throw new Error("全ゼロGUIDが残っています");
}
console.log("Rendered JSON: PASS");
console.log("Remaining token count: 0");
console.log("Zero GUID remains: false");
' "$RENDERED_MANIFEST"2026年9月8日の実測では、元ファイルと生成後ファイルのJSON構文は正常でした。
未置換トークンは0件で、全ゼロGUIDも残っていませんでした。ただし、これはJSON構文と置換結果の確認であり、まだTeamsアプリとしての検証結果ではありません。
atk validateでTeamsアプリマニフェストを検証する
生成したファイルを指定して検証します。
終了コードは、別のコマンドを実行する前に保存してください。
atk validate --manifest-file "$RENDERED_MANIFEST" -i false
VALIDATE_EXIT_CODE=$?
echo "Exit code: $VALIDATE_EXIT_CODE"-i falseは、対話入力を求めないことを明示する指定です。CLI 1.1.16のatk validate -hでは既定値もfalseでしたが、CIでの実行意図が分かるように明示しています。
実際の出力は次のとおりでした。

スキーマと検証ルールの両方でAll passedが表示され、終了コードは0でした。
終了コード0は、シェルスクリプトやCIでコマンドの成功判定に利用できます。
なお、出力にはapp packageという表現がありますが、今回CLIへ渡したのは生成したマニフェストファイルです。ZIPやアイコンまで検証した結果ではありません。
All passedでも確認できないこと
All passedは、Teamsアプリ全体の動作を保証するものではありません。
今回の検証では、次の項目を確認できません。
- 完成版ZIPをTeamsへアップロードできるか
contentUrlの実URLへ到達できるか- Teamsのiframe内で画面を表示できるか
- CSP、TeamsJS、認証が正しく動作するか
- テナントのアプリポリシーや配布条件に適合するか
正式なApp IDと実URLを反映したmanifest.jsonを再検証し、アイコンを含むZIPとTeams上の動作も別途確認する必要があります。
Teamsアプリマニフェスト検証のまとめ
JSON構文確認と、Teamsのスキーマ/検証ルールは役割が異なります。
プレースホルダーへ検証用の値を入れた検証用ファイルを作れば、元のテンプレートを上書きせずにatk validateを実行できます。
CLI 1.1.16による実測では、スキーマと検証ルールがともにAll passedとなり、終了コードは0でした。
ただし、公開前には完成版マニフェスト、ZIP、Teams上の画面表示、認証、配布条件も確認してください。
参考文献
公式情報の確認日:2026年9月8日

