AI チームメイト開発スキル
Foundry hosted agent を Agent 365 Autopilot として発行し、Teams / Microsoft 365 Copilot の
**同僚エージェント(agentUser)**として実際に会話できる状態にする。評価Hub、Python
EvaluationWorker、Foundry Monitor/Evaluations まで初回 scaffold / publish の標準範囲に含める。
agentUser を持たせる経路は 2 つある。 既定は Foundry Autopilot(hire したインスタンスごとに
agent user アカウントが払い出される。Frontier preview が前提)
→ references/foundry-autopilot.md。
App Service 自己ホストは、独自ランタイム制御が必要な場合の互換経路として残す。
旧来の「Foundry の activityprotocol を Azure Bot に直結する方式」は使わない。
Agent 365 のトークンが 401 で拒否され、Teams で話しかけても応答が返ってこない(無反応)。
参考情報としてのみ references/foundry-hosted-bot.md に隔離する。
本 SKILL.md には正常系フローだけを置く。手順の中身・分岐・異常系はすべて references/、
再現可能な操作は scripts/ にある。
必須ルーティング・完了契約
- AI teammate / AIチームメイト / AI チームメイト / Agent Template / Foundry Autopilot の依頼では本スキルを必ず読む。
明示的な自己ホスト要件がなければ
hosting: "foundry-autopilot" を decisions JSON に明記し、
references/foundry-autopilot.md の手順と
scripts/publish_foundry_autopilot.py --check → --execute を使う。
汎用 scripts/deploy.py や SDK の agents.create_version だけで Agent template を発行したことにしない。
- 明示的な Agent Template / Autopilot 要求でプレビュー参加・ライセンス・権限・対応リージョンなどの
前提が不足/未確認なら停止する。 不足と必要な担当者を報告し、通常 Agent・共有 bot・自己ホストへ
自動で切り替えない。自己ホスト要件はサポートする別経路であり、経路変更には利用者の明示的な合意が必要。
- Autopilot は 同じ agent version の
digital_worker_type=m365 と、その応答の
blueprint.client_id に結び付く agenticUserTemplate.AgentIdentityBlueprintId を用い、
publishAsAutopilot=true・useAgenticUserTemplate=true・agenticUserTemplate を揃えて発行する。
- HTTP 200、通常の Registry 行、
teamsAppId / titleId の取得だけでは完了しない。
M365 管理センター Requests の対象行の Type = Agent template を手動確認し、承認後に Teams の
Agents for your team から採用(hire)でき、agent user が払い出されることを確認してから完了とする。
カタログ登録までの依頼でも Type を確認し、採用未確認なら「登録済み・採用未確認」と報告する。
UI を確認できない場合は承認待ち/採用待ちとして止め、推測の read-back API で代用しない。
--container-only は既存の検証済み Agent template のコード更新だけ。
初回発行、Type 未確認、通常 Agent の修復には使わず、完全な発行と UI 検証を行う。
確認済みの場合も --confirm-existing-template を明示する。生成 deploy.ps1 は既定で完全発行し、
コードのみ更新する場合だけ -ContainerOnly -ConfirmExistingTemplate を指定する。
build_teams_package.py も Agent template を必須とし、blueprint 不足時の共有 Agent への降格は行わない。
| 原則 | 内容 |
|---|
| 既定は Foundry Autopilot | AI チームメイトは hosting: "foundry-autopilot" を明記して Agent template として発行する。独自ランタイムなど明示的な自己ホスト要件は別経路で扱い、前提不足時の代替にしない |
| activityprotocol 直結は不可 | Foundry の activityprotocol を Azure Bot のエンドポイントにする旧方式は agentUser チャットが動かない |
| API 優先 | Azure CLI・a365 CLI・Agents SDK を優先し、M365 管理センター限定の操作だけ承認済み private API plan をログイン済みブラウザで実行する |
| テンプレート駆動 | コミットするのは ${VAR} 入りテンプレートだけ。実値は .env / シークレットストアのみ |
| 外部データはデータ | 取り込んだ文章はフェンスで囲って渡し、実害のある操作はコードで ID を検証する |
| インスタンス単位 | 同意・写真・Dataverse 登録はインスタンスごと。作り直すたびにやり直す |
| ALM は委譲 | pre-commit・CI/CD・レビューゲート・リリース記録は alm スキルが担当する |
前提ツール: Python 3.10+、Azure CLI(az)、Agent 365 CLI(a365)、.NET 8 SDK、Git。
認証は standard/scripts/auth_helper.py のキャッシュを共有し、foundry-autopilot 用に個別ログインしない。
事前確認(会話の最初に 1 回だけ)
本スキルの利用が確定したら、1 回の AskUserQuestion で次の 9 点をまとめて確認する。
以降の Step で同じ内容を聞き直さない。
| # | 質問 | 選択肢 / 記入例 |
|---|
| 1 | ゴールはどこまでか | (a) ローカル scaffold のみ(Azure 操作なし)<br>(b) 自己ホスト App Service の endpoint を用意するまで(Step 1〜6)<br>(c) M365 管理センターに "Agent template" として登録するまで(Teams チャットはまだ動かない)<br>(d) Teams で実際に会話できる状態まで(Step 0〜13・Azure 課金あり) |
| 2 | Azure サブスクリプション、リソース作成権限、ロール割り当て権限、認証キャッシュは使えるか | Autopilot は Foundry hosted agents 対応リージョンと Azure RBAC の担当者を確認する。明示選択の自己ホストでは App Service B1+、Azure Bot、UAMI の作成可否も確認する |
| 3 | Frontier for Autopilot の前提と割り当て担当者は確認済みか | Foundry Autopilot で採用した agent user に Microsoft 365 Frontier for Autopilot を割り当てる。Agent 365 SKU の空席確認・割り当てはしない |
| 4 | devPreview または別のプレビュー機能を使うか | (c)/(d) は本スキルの devPreview Agent template を使うため Frontier が必要。テナントの Frontier 参加と、管理者に必要な Microsoft Copilot ライセンスを確認する |
| 5 | 各管理操作の担当者とロールは誰か | Agent Registry: AI Administrator、blueprint 作成: Agent ID Developer、インスタンス同意: Privileged Role Administrator、Microsoft 365 Frontier for Autopilot 割当: License Administrator。Global Administrator は代替に限定する |
| 6 | 「〇〇を行ってくれる同僚エージェント」の具体的な業務内容は? | digital-colleague-design.md §2 の役割カタログ(R1〜R6)を選択肢として提示する(複数可・自由記述可) |
| 7 | エージェント名、表示名、owner / sponsor、公開・テスト対象、アイコンは? | kebab-case 名、Teams 表示名、ユーザーまたはセキュリティ グループを確認する。希望が無ければ名称を 3 案提案する。アイコンは正方形・背景透過 PNG。商標・著作権に触れる名称やキャラクターは使わない |
| 8 | 頭脳(B3)の実装方式はどちらにするか | (a) GitHub Copilot SDK ランタイム(BYOK + Managed Identity・既定) — 計画・ツール反復・コンテキスト圧縮をランタイムに任せる<br>(b) 自前 Chat Completions ループ — 反復回数を自分で抑える。子プロセスを起動できないホスト向け<br>→ 判断材料は copilot-sdk-runtime.md |
| 9 | どこでホストするか | (a) 自己ホスト(明示選択時のみ) — App Service + Azure Bot を自分で持つ。C# / .NET。頭脳は (a)(b) どちらも選べる<br>(b) Foundry Autopilot(既定) — Foundry がホスティングを持つ。Python。Bot 登録も App Service も不要だが 頭脳は Copilot SDK に固定される。前提不足なら停止し、(a) へ自動変更しない<br>→ 判断材料は foundry-autopilot.md |
質問 1 の回答がテナントのアプリカタログへの公開の承認を兼ねる。
(a) は課金もカタログ公開も発生せず、(b) は Azure Bot / App Service の課金だけが発生する。
Foundry Autopilot を選んだときに追加で聞く 5 点
質問 9 が (b) のときは、全機能(B1〜B17 のうち Autopilot で動くものすべて)を scaffold する前提で、
機能の取捨選択ではなく、安全に動かすための判断だけを同じ AskUserQuestion で聞く。
回答は decisions JSON の対応するキーへ書き、プロンプトとコンテナー設定に反映される。
| # | 質問 | decisions のキー | 反映先 |
|---|
| A | どんなルール・判断基準なら共有してよいか(本人 / 同じ部署 / 他部署 / 社外) | sharingPolicy(箇条書きの配列) | prompts/system.md の「共有と同意」 |
| B | どんなデータは、他の人に共有する前に必ず確認を取るべきか | sensitiveData(配列) | 同上(共有前に内容を示して明示的な確認を取る) |
| C | 外部からの入口としてメールを有効にするか | emailEnabled(true / false) | EMAIL_CHANNEL_ENABLED。false なら自分宛てメールに返信しない |
| D | 話し方などのキャラクター設定(一人称・敬語の度合い・口癖・避けること) | personality | プロンプト冒頭 |
| E | プロフィール画像(手元の画像 / 説明から生成 / 後で) | profileImage({"mode":"file","path"} / {"mode":"generate","prompt"} / "none") | assets/profile.png → 採用後に set_agent_user_photo.py |
- A・B は選択肢に既定案(本人は自由・社内は同意制・社外不可 / 個人情報・未発表数値・社外秘)を出し、
自由記述で足してもらう。無回答なら既定案が入る。匿名リンク禁止・社外共有禁止はコード側でも強制される。
- C を有効にすると、届いたメールは外部データとして囲い、メール経路では共有・Teams 送信をコードで止める。
- E の生成は
IMAGE_MODEL_DEPLOYMENT を使う(generate_profile_image.py)。実在の人物・既存キャラクターは描かない。
- 定期実行(B11)は常に含め、scaffold が
SCHEDULE_ENABLED=true を .env に書く。発行後に
provision_schedule_trigger.py --execute で Logic App を作る(→ troubleshooting.md #88)。
- 発行後の承認は、管理センターの Requests に出る表示名の行(Agent template)の Publish ウィザードで行う
(Activate の対象 → ポリシー → Grant admin consent → Publish)。その後 Teams の Agents for your team から採用する
(→ foundry-autopilot.md §6)。Registry の
AGENT_NAME の行は削除しない。
Foundry Autopilot の agent user に Agent 365 SKU を割り当てない。
採用後の agent user に割り当てるライセンスは Microsoft 365 Frontier for Autopilot。
Agent 365 は blueprint / agent identity の機能名であり、Autopilot の agent user ライセンス空席を
AGENT_365 SKU で事前確認しない。Frontier プレビューのテナント参加要件とは区別し、
agent user が払い出された後に Frontier for Autopilot を割り当てる。
工程別の最小権限:
| 工程 | 推奨ロール | 注記 |
|---|
| Microsoft 365 Frontier for Autopilot を agent user に割り当てる | License Administrator | agent user の払い出し後に割り当てる。usageLocation と利用可能 SKU を確認する |
| Frontier 設定 | AI Administrator / Security Administrator / Office Apps Administrator | 管理者自身にも Microsoft Copilot ライセンスが必要 |
| Agent ID blueprint 作成 | Agent ID Developer | 作成者は blueprint と blueprint principal の owner になる |
| Agent ID のフル ライフサイクル | AI Administrator / Agent ID Administrator | instance / agentUser を含む管理 |
| M365 Agent Registry への追加・公開・配布 | AI Administrator | Global Administrator は緊急時の代替のみ |
| インスタンスへのテナント全体 OAuth 同意 | Privileged Role Administrator | Global Administrator は代替。インスタンス再作成ごとに必要 |
質問 6 の回答から、依頼者が言っていない機能ブロックを自分から提案する。
依頼者は「Web 検索が欲しい」「定期実行を付けて」とは言わない。
社外の情報が出てきたら B10、繰り返しの仕事が見えたら B11、ファイルが出てきたら B12、
B12 を入れるなら B13 と B14、相手からファイルを渡されるなら B16 をその場で提案し、可否を取る
(提案条件と言い回しは digital-colleague-design.md §4)。
資料を作らせるなら B12 は必須。 「資料をまとめて」「PowerPoint にして」は
依頼者から見れば普通の依頼だが、B12 が無いとエージェントはコードを書けるが実行できない。
モデルはそれを知らずに OOXML を手組みし始め、ターン丸々を使って何も渡せない。
受け取り時に deploy_ai_teammate.py --check がこの不整合(Sandbox.Enabled だけが true)を落とす。
「有効だが実体が無い」は B12 に限らない。 --check は特定ブロックを名指しせず、
scaffold 側の BLOCK_SETTINGS / BLOCK_FILES から検査対象を導出するので、
ブロックを増やしても検査が追従する。落とすのは次の 4 形態。
| 形態 | 症状 |
|---|
| セクションが有効/C# ファイルが無い | ツールが存在せず、依頼に無言で失敗する |
ファイルはあるが Program.cs に未登録 | DI に入らず、ツールがモデルに届かない |
有効/${...} が未解決(Sandbox.Endpoint 等) | 実行時に初めて落ちる |
Skills.Enabled=true / skills/ が空 | 役割どおりの手順を持たないまま答える |
制約もこの場で先に伝える(同 §5)。とくに「メールは push されないのでポーリングになる」
「エージェントはメールを既読にできない」「他人の予定表は直接読めない」
「共有リンクは一度渡すと取り消せない」の 4 点は、後から言うと要件が崩れる。
一括 scaffold(Step 0〜3 をまとめて実行する)
1 回の AskUserQuestion で集めた回答は、利用者に手入力させず、エージェントが
references/scaffold-decisions.example.json の
スキーマに沿った JSON へ自分で書き出す。 役割 / 機能ブロック / 頭脳の実装方式(runtime) /
poc・full / GitHub リポジトリ(full のときは private を既定)/ 公開範囲 / 管理担当者を
この 1 ファイルにまとめ、
scripts/scaffold_ai_teammate.py に渡すと、Step 0〜3 が一度に終わる。
python scripts/scaffold_ai_teammate.py --decisions decisions.json --env .env --target .
-
役割ベースの構成可能テンプレート(preset: "role" + roles / blocks)と、
Meena 互換の全部入り(preset: "full" → B1〜B17 すべて)の両方に対応する。
-
頭脳(B3)は runtime で選ぶ。"copilot-sdk"(既定)なら CopilotRuntime.cs と
Copilot ランタイム版 AgentBrain.cs、"agents-sdk" なら Chat Completions 版 AgentBrain.cs が
生成され、Agent.csproj のパッケージ参照と appsettings.json の Copilot セクションも揃う
(→ copilot-sdk-runtime.md)。
-
ホスティングは hosting で選ぶ。runtime とは別の軸であることに注意する。
hosting | 生成されるもの | runtime |
|---|
"self-hosted"(明示選択時のみ) | C# の Agents SDK プロジェクト + App Service / Azure Bot | copilot-sdk / agents-sdk |
"foundry-autopilot"(本スキルの既定) | Microsoft 公式クイックスタート(Python)を取得し、本スキルのオーバーレイを重ねる | copilot-sdk に固定 |
スクリプトの省略時既定値に依存せず、hosting を必ず書く。 Autopilot 要求に
"self-hosted" を書いたり、hosting を省いて自己ホストへ流したりしない。
foundry-autopilot で runtime を明示的に agents-sdk にすると scaffold はエラーで止まる。
矛盾した設定を黙って直すと、意図しない頭脳で動くエージェントが出来上がる。
-
回帰テストのケースは regression/suite.json へ出力される。選ばなかった機能ブロックの
ケースは requiresBlocks を見て除外される(→ regression-tests.md)。
-
選ばなかった機能ブロックの設定セクションは appsettings.json から消える。
Sandbox.Enabled=true と ${SANDBOX_ENDPOINT} だけが残ると、コードを実行できないのに
実行できるつもりのエージェントになり、依頼を受けて何も返さない。
-
Agent Skills は scaffold 時に既定で導入されるので、Skills.Enabled=true と空の skills/ が
同居することはない(--no-skills で抑止した場合は --check が落とす)。
-
Code Apps の「AI チームメイト評価Hub」は常に同時 scaffold される(evaluation-app/ 配下)。
無効化はできない。
-
評価Hub は環境に 1 つを全チームメイトで共用する。名前はチームメイト名に寄せず
「AI チームメイト評価Hub」で固定し、誰の行かは <prefix>_agentkey で区別する。
チームメイトごとに別 Hub を作ると、評価履歴がアプリ単位に分断されて互いに見えなくなる。
- 「組織図」ページ …
<prefix>_evalagent の上長キーでチームメイトの階層を表示する。
最上位には .env の VITE_ORG_OWNER_* で指定した人間のオーナーを置き、各チームメイトの
AGENT_MANAGER_KEY を VITE_ORG_OWNER_KEY に合わせるとその下に並ぶ。オーナーは Dataverse の
マスター行を持たない(人間を evalagent に入れるとチームメイトの絞り込みに混ざる)。
- 「自動テスト」ページ … 同じ依頼を複数のチームメイトへ同時に投げ、所要時間・応答・
自動採点・手動評価・改善方針プロンプト・GitHub Issue 起票までを 1 画面で回す。
- 「スキル」ページ … 各チームメイトの
SkillSync が自分の skills/ 配下の SKILL.md を
<prefix>_skill へ写しているものを表示する。スキルはエージェントのファイルとしてしか
存在しないので、この同期が無いと Code App からは永遠に見えない(<prefix>_skills が
無いままだと Resource not found for the segment で落ちる)。
- 「フィードバック」ページ … チームメイトが利用者の代わりに Dataverse MCP で書く
<prefix>_aiteammatefeedback を表示する。書いたのはエージェントなので createdby は使えず、
依頼者は <prefix>_requester(systemuser への Lookup)と氏名・メールのテキストで持つ。
- 「AIチームメイトの設計」の各ページ(Agent Brain 設定 / セキュリティ設定)… 画面上部の
チームメイト切替(
AgentSwitcher)で誰の設計を見るかを選び、選択は URL の ?agent= に入る。
セルフホストの実装は全員で共通なので既定では共通の写しを見せ、実装が分かれるチームメイトだけ
AGENT_BRAIN_OVERRIDES / AGENT_SECURITY_OVERRIDES にエージェントキーで差分を書く。
設計ドキュメントは src/data/design-specs/<エージェントキー>.md を置けばそちらが優先される。
共通の写しを見ているときは画面にその旨を出す(誰の設計か分からないまま読ませない)。
自動テストは Code App から直接エージェントを呼ばない。 チームメイトの messaging endpoint は
そのエージェント宛に署名された Bot Framework の通信しか受け付けないので、アプリから叩くことはできない。
依頼は <prefix>_evaltestresult の行として積み、各チームメイトの TestWorker が
自分の agentkey の行だけを拾って応答と所要時間を書き戻す。止まっているチームメイトの行は
「待機中」のまま残るだけなので、動いている相手の比較結果は失われない。
- 選ばなかった機能ブロックの C# ファイルと DI 登録は自動的に除かれる(
full は全部入りで生成される)。
target が空でない場合は既定で失敗する(--force で明示的に上書きする)。
${VAR} が .env に無く未解決のまま残る場合はエラーで停止する
(デプロイ時にしか埋まらない値は .env.example の説明どおり後回しでよい)。
implementationMode: "full" を選ぶと ALM の pre-commit ゲートと CI ワークフローも同時に生成される。
基本フローは「一括 scaffold → 選択した経路で初回発行・検証 → 個別開発」にする。
ゼロから手でファイルを並べる別ルートは正常系に持たない。最初の AskUserQuestion で分かっている要望は
役割・機能ブロックとしてテンプレートへ反映し、Step 3 でカスタム済みの初期実装を生成する。
Autopilot は publish_foundry_autopilot.py --check → --execute と
references/foundry-autopilot.md §6 の UI 検証を通す。
明示選択の自己ホストだけが Step 6 の deploy_ai_teammate.py --check → --execute を使う。
追加要望も同じ経路で反映し、コード更新専用の省略手順を初回公開へ流用しない。
スキル同梱スクリプト
値は引数または .env(references/.env.example)から取得する。
| スクリプト | 用途 | Step |
|---|
| scaffold_ai_teammate.py | 1 回の AskUserQuestion の回答(decisions JSON)から同僚エージェント + 評価Hub を同時 scaffold する | 0〜3 |
| deploy_ai_teammate.py | --check(検証のみ)→ --execute(Dataverse スキーマ作成・自己ホスト展開・評価Hub デプロイ)の 2 段階デプロイ。pa app init / 接続参照 / add-data-source / npm run predeploy を正しい順序で実行する。M365 管理センターの devPreview 公開は別の承認 plan として案内する | 6・9〜11 |
| setup_evaluation_dataverse.py | 評価Hub の 9 テーブル(evalagent/evalturn/evalrule/evalresult/evaljob/evaltestrun/evaltestresult/skill/aiteammatefeedback)を PUBLISHER_PREFIX で冪等作成・列補完し、自分のチームメイト行を登録する。--check は作成せず不足だけ列挙する | 3・6 |
| setup_agent_dataverse_user.py | エージェントの マネージド ID に Dataverse のアプリケーション ユーザーと専用ロール(上記 9 テーブルの Global 権限だけ)を冪等に与える。これが無いと常駐ワーカーの Dataverse 呼び出しが全部 403 になる。テーブルを追加したら必ず再実行する | 3・6 |
| provision_selfhost.py | UAMI + Azure Bot(Teams チャネル)+ App Service を冪等に作成し .env へ書き戻す。--check でプラン・Always On のドリフト検出 | 6 |
| deploy_agent_webapp.py | ブループリント作成/シークレット ローテーション(App Service 設定へのみ注入・ログ非出力)・dotnet publish・az webapp deploy/restart・a365 setup blueprint --endpoint-only を実行する | 4・6 |
| provision_code_sandbox.py | コード実行サンドボックス(Container Apps 動的セッション プール)を冪等に作成しロールを付与。B12 のとき deploy_ai_teammate.py --execute が発行前に自動実行する | 6・8 |
| install_agent_skills.py | 既定の Agent Skills を GitHub リリースから skills/ へ展開する。scaffold_ai_teammate.py が自動実行し、--check でドリフト検出 | 3・6 |
| check_copilot_sdk_env.py | Copilot SDK ランタイムの前提チェック(.NET SDK / 作業ディレクトリがリポジトリ外か / BaseDirectory 書込可否 / BYOK エンドポイント形式 / Entra トークン取得)。ローカルとデプロイ先の両方で実行する | 3・6 |
| provision_image_model.py | 対象アカウントで提供される画像モデル名・バージョンを確認してから冪等にデプロイする。--check は変更なし。発行より前に実行する(デプロイメントが無いまま発行すると generate_image が 401 で落ちる) | 6・8 |
| build_teams_package.py | Teams manifest + アイコン + agenticUser.json を ZIP 化 | 9 |
| plan_agent_template_upload.py | devPreview ZIP の内容・SHA-256・対象 tenant・固定 endpoint を検証し staging approval plan を生成 | 10 |
| agent_template_browser_runner.mjs | ログイン済み M365 管理センターで tenant を照合し、承認済み staging と別承認の FINALIZEPACKAGE、read-back を実行 | 10 |
| publish_teams_app.py | Graph で ZIP を組織カタログへ登録(devPreview は Graph 側で拒否される) | 10 |
| grant_agent_instance_consent.py | インスタンス SP に Messaging Bot API の管理者同意を付与 | 11 |
| grant_agent_graph_scopes.py | インスタンス SP に Microsoft Graph の委任スコープを付与(既存の同意へマージ)。--resource-app-id で Dataverse など他のリソースにも使える | 11 |
| connect_agent_dataverse.py | エージェンティック ユーザーを Dataverse 環境に追加し、許可 MCP クライアントに登録し、読み取り専用ロール(検索+指定接頭辞のテーブルの Read)を作って割り当てる。--check あり(troubleshooting.md #85) | 11 |
| set_agent_user_photo.py | エージェンティック ユーザーにプロフィール写真を設定 | 12 |
| configure_agent_presence.py | UAMI に Graph プレゼンス権限を冪等付与し設定値を確認 | 12 |
| query_agent_logs.py | Application Insights の AppTraces を az rest で読む(az monitor 系はワークスペース ベースで失敗するか対話プロンプトで止まる→ troubleshooting.md #71) | 全般 |
| run_regression_tests.py | 回帰テスト。--check は不変条件だけ(無料・決定的)、--execute は評価ハブのキュー経由で実ターンを回す。JUnit XML / Markdown を出力し、deploy_ai_teammate.py --execute が最後に自動実行する | 13 |
| setup_foundry_evaluation.py | Foundry 標準の Evaluations を設定する。Autopilot 発行時は publish_foundry_autopilot.py が --mode scheduled で自動実行し、このスクリプトは単独の確認・修復にも使える | 13 |
| fetch_autopilot_quickstart.py | Microsoft 公式の Foundry Autopilot クイックスタートをフォークせずに取得する(hosting: "foundry-autopilot" のとき scaffold が自動実行) | 3 |
| publish_foundry_autopilot.py | Autopilot 必須の発行経路。Foundry hosted agent のバージョン作成、Foundry Monitor/Evaluations の自動構成、M365 publish。accessBoundaries の付与・インスタンス ID の有効化・--bump-version を含む。IMAGE_MODEL_DEPLOYMENT があればコンテナへ渡し、実在を検証し、アカウント スコープのロールも付ける。--container-only は既存の検証済み Agent template のコード更新専用(初回発行・通常 Agent の修復は禁止)。SCHEDULE_ENABLED=true なら Invocations を公開する(troubleshooting.md #89) | 6・10 |
| provision_schedule_trigger.py | Foundry Autopilot の定期実行(B11)を起こす Logic App(システム割り当て MI・Foundry Agent Consumer・既定 15 分ごと)を作る。--tick-now で 1 回だけ起こす(troubleshooting.md #88) | 10 |
| setup_autopilot_instance.py | Foundry Autopilot の採用後の設定を 1 本で行う(委任スコープ〔リアクションの ChatMessage.Send 含む〕・Dataverse 接続・評価ハブのアプリケーション ユーザーとマスター行・顔写真)。既定は計画表示、--execute で適用(foundry-autopilot.md §6) | 11 |
| generate_profile_image.py | AskUserQuestion で「説明から生成」を選んだプロフィール画像を、テナントの画像モデルで描いて assets/profile.png に書く | 12 |
すべて --check で確認のみの実行ができる(query_agent_logs.py は読むだけなので不要)。
discover_foundry_context.py / create_blueprint.py / create_instance.py / deploy.py は
Foundry 連携の参考スクリプトで、正常系では使わない
(→ references/foundry-hosted-bot.md)。
とくに deploy.py / SDK agents.create_version だけで Autopilot / Agent Template の発行を代替しない。
ALM 共通スクリプト(render.py / sanitize.py / check_secrets.py 等)は alm スキルが提供する。
標準フォルダ構成
以下は自己ホストの構成。Autopilot は
references/foundry-autopilot.md §9 の Python scaffold を使う。
<repo-root>/
├── .env # 実値(.gitignore 済み)
├── .env.example # プレースホルダーのみ(コミット対象)
├── agents/<agent-name>/
│ ├── agent.template.yaml # コミット対象(${VAR} 入り)
│ └── agent.yaml # レンダリング結果(.gitignore 済み)
├── src/<agent-name>-agent/ # Agents SDK アプリ(自己ホスト)
│ ├── Program.cs / <Agent>.cs # AgentApplication 派生。Teams message を受けて応答する
│ ├── AgentBrain.cs # LLM + ツール ループ(全入口で共用)
│ ├── appsettings.json # agentic 設定。シークレットは書かない
│ └── (機能ブロックのファイルは Step 8 で足す → references/feature-blocks.md)
├── teams/
│ ├── manifest.template.json # コミット対象
│ ├── agenticUser.template.json # コミット対象
│ └── <agent-name>-teams-app.zip # ビルド結果(.gitignore 済み)
├── assets/agent-icon.png # 正方形・背景透過(AGENT_ICON 未指定時に使用)
└── scripts/ # 本スキルの scripts/ をコピー
正常系フロー
最初に hosting を確定する。Autopilot は Step 0〜3 の scaffold 後、
references/foundry-autopilot.md §5〜6 の発行・承認・採用へ進む。
以下の Step 4〜12 は明示選択の自己ホスト用で、Autopilot に追加実行しない。
回帰テスト・評価は選択した経路の参照に従う。
Step 0: 役割と機能ブロックを決める
何を作るかを決めずに Step 1 へ進まない。
references/digital-colleague-design.md に従い、
役割(§2 の R1〜R6)・機能ブロック(§3・§4。全部は入れない)・
段階(§7 の L1〜L5)の 3 つを確定する。決まったブロックが以降の実施範囲を決める。
あわせて 頭脳(B3)の実装方式をここで決める(→ copilot-sdk-runtime.md)。
AgentBrain.cs が丸ごと入れ替わるため、作り込んだ後の変更は書き直しになる。
runtime | ツール ループ | 選ぶ基準 |
|---|
copilot-sdk(既定) | GitHub Copilot SDK ランタイム(BYOK + Managed Identity) | 調べもの・資料作成など、手順が事前に決まらない仕事 |
agents-sdk | アプリ内の Chat Completions ループ | 手順が決まっている・子プロセスを起動できないホスト |
| ブロック | 実施する Step |
|---|
| B1 Teams 会話 / B3 頭脳 / B8 人格 | Step 5・6・7 |
| B4 Microsoft 365 接続 / B5 Dataverse 接続 | agent-brain.md §6・§7 |
| B2 自分の ID / B6 メール / B9 チャット / B10 Web / B11 定期 / B12 作業環境 / B13 経過 / B14 共有 / B15 実績 / B16 添付 / B17 画像生成 | Step 8 |
| B7 Teams プレゼンス | Step 12 |
Step 1: 名前・表示名・アイコンを決める
顔(表示名とアイコン)は Teams パッケージに焼き込まれるので、Step 9 のビルド前に確定させる。
後から直すには再アップロードが要る(→ architecture.md §5)。
アイコンは Step 12 のプロフィール写真にも流用する。
AGENT_NAME=mina-secretary # kebab-case。フォルダ・リソース名
AGENT_DISPLAY_NAME=秘書 ミーナ # 30 文字以内。Teams の表示名(AGENT_NAME とは別物)
AGENT_FULL_NAME=秘書 ミーナ - 予定とメールを掃く同僚エージェント # 100 文字以内
AGENT_ICON=assets/agent-icon.png # アイコン画像のファイルパス
AGENT_ICON の解決順は --icon 引数 › AGENT_ICON › assets/agent-icon.png。
独自アイコンはアルファチャンネル付きの正方形 PNG(512x512 推奨)にする。
背景を透過にしないと Step 9 の outline アイコンが塗り潰しになる。
商標・著作権に触れる意匠やキャラクターは使わない。
Step 2: decisions.json と .env を用意する
Step 0 で決めた内容を scaffold-decisions.example.json の
形へ書き出す(利用者に手入力させず、エージェントがこの JSON へ書く)。
Copy-Item .github/skills/foundry-autopilot/references/.env.example .env.example
Copy-Item .env.example .env # 値を埋める(AZURE_* / DATAVERSE_URL / AZURE_OPENAI_* など)
New-Item -ItemType Directory assets -Force | Out-Null
Copy-Item C:/path/to/your-icon.png assets/agent-icon.png
最低限 AZURE_SUBSCRIPTION_ID / AZURE_TENANT_ID / AZURE_RESOURCE_GROUP /
DATAVERSE_URL / ENV_ID / SOLUTION_NAME / PUBLISHER_PREFIX / AZURE_OPENAI_ENDPOINT /
AZURE_OPENAI_DEPLOYMENT を入れる(未解決の ${VAR} が残ると Step 3 の scaffold が失敗する)。
認証は standard/scripts/auth_helper.py が保存したキャッシュを使い、
az login / a365 の個別ログインを増やさない。
自己ホスト経路だけは Foundry プロジェクトの設定が不要。 Autopilot は
FOUNDRY_PROJECT_ENDPOINT など references/foundry-autopilot.md §5 の
設定が必要で、未設定を自己ホストへの切り替え理由にしない。
Step 3: 一括 scaffold する(同僚エージェント + 評価Hub を同時生成)
python .github/skills/foundry-autopilot/scripts/scaffold_ai_teammate.py `
--decisions decisions.json --env .env --target .
--target . は空のリポジトリ ルート、または --force を付けて既存リポジトリへマージする。
- 生成される主なもの:
Agent.csproj / Program.cs / Agent.cs / AgentBrain.cs などの
Agents SDK プロジェクト一式(選んだ機能ブロックと runtime の分だけ。
runtime: "copilot-sdk" なら CopilotRuntime.cs も)、prompts/system.md、
evaluation-app/(AI チームメイト評価Hub。Code Apps。常に生成)、scaffold-plan.json(確定した構成の記録)。
.gitignore は汎用化と秘匿化の一覧を満たすこと。
本格実装(implementationMode: "full")のリポジトリ雛形・hook・CI 定義は
scaffold が同時生成し、詳細は alm スキルに従う。
Step 4: Agent 365 のエージェント ID ブループリントを作成する
Foundry のブループリントとは別物(→ architecture.md §1)。
ここで作るのは agentUser インスタンスを払い出すための Agent 365 側の設計図。
a365 setup blueprint -n <agent-name> --no-endpoint
- 生成された
a365.generated.config.json の agentBlueprintId を .env の
A365_AGENT_BLUEPRINT_ID に設定する。
- クライアントシークレットが平文で標準出力される。ログに残さない。
- 初回はディレクトリ伝播の遅延で失敗することがあるが、再実行すれば冪等に修復される。
- エンドポイント登録は Step 6 で行う(この時点ではまだ URL が存在しない)。
Step 5: scaffold 済み Agents SDK アプリを初期要望に合わせる
Step 3 で生成したアプリが agentUser チャットの実体。 選択した役割・機能ブロック、プロンプト、
環境設定が初期要望と一致することを確認し、テンプレートでは表現できない業務固有部分だけを実装する。
src/<agent-name>-agent/
├── <agent-name>.csproj # Microsoft.Agents.Hosting.AspNetCore / Authentication.Msal
├── Program.cs # AddAgent / AddAgentAspNetAuthentication / MapAgentApplicationEndpoints
├── <Agent>.cs # AgentApplication 派生
├── AgentBrain.cs # LLM / ツール呼び出し(runtime で中身が変わる)
├── CopilotRuntime.cs # runtime: "copilot-sdk" のときだけ
└── appsettings.json # シークレットは書かない
appsettings.json は references/self-hosted-agent.md §3 に従う。
外せない固定点は 4 つ。
AuthType は confidential client(ClientSecret / 証明書 / フェデレーション資格情報)
ClientId は A365_AGENT_BLUEPRINT_ID(Bot の appId ではない)
Scopes は 5a807f24-c9de-44ee-a3a7-329e88a00ffc/.default
TokenValidation:Audiences に ブループリント appId と Bot の msaAppId を両方入れる
Step 6: デプロイして messaging endpoint を登録する
ここからは明示選択した自己ホスト経路の手順。Autopilot は references/foundry-autopilot.md §5〜6 で発行・承認・採用し、この App Service 手順へ流さない。 自己ホストの手順とログの読み方は
references/self-hosted-agent.md。
★ App Service は B1 以上 + Always On。Free / Shared には Always On が無く、
アプリがアンロードされてすべての BackgroundService(B6・B11・B12)が止まる。
さらにアンロード後の 1 通目はコールド スタート(55〜80 秒)に負けて捨てられる
(チャネルは再送しない)。「久しぶりに話しかけると 1 回めだけ無視される」はこれ(→ troubleshooting #44)。
provision_selfhost.py が F1/D1 を弾き、Always On を有効化し、成功時にも読み戻して検証する。
python scripts/deploy_ai_teammate.py --execute がここから下を自動で行う
(provision_selfhost.py → deploy_agent_webapp.py)。
以下は deploy_agent_webapp.py が実行する内容そのもの(手動で追う場合や障害調査用の参考)。
# 1. UAMI + Azure Bot(Teams チャネル) + App Service を作成し .env に書き戻す
python scripts/provision_selfhost.py --write .env
# 2. ブループリント用シークレットを App Service のアプリ設定へ注入(ファイルには書かない)
$sec = az ad app credential reset --id $env:A365_AGENT_BLUEPRINT_ID --append `
--display-name "$env:AGENT_NAME-agent" --years 1 --query password -o tsv
az webapp config appsettings set -g $env:AZURE_RESOURCE_GROUP -n $env:AGENT_WEBAPP_NAME `
--settings "Connections__ServiceConnection__Settings__ClientSecret=$sec"
Remove-Variable sec
# 3. デプロイ(発行前に publish フォルダを必ず削除する)
Remove-Item .\publish -Recurse -Force -ErrorAction SilentlyContinue
dotnet publish -c Release -o .\publish
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\publish", "$PWD\publish.zip")
az webapp deploy -g $env:AZURE_RESOURCE_GROUP -n $env:AGENT_WEBAPP_NAME `
--src-path .\publish.zip --type zip --track-status false --timeout 600000
az webapp restart -g $env:AZURE_RESOURCE_GROUP -n $env:AGENT_WEBAPP_NAME
# 4. ブループリントにエンドポイントを登録(Step 4 と同じカレントディレクトリで実行)
a365 setup blueprint -n <agent-name> --endpoint-only --messaging-endpoint $env:AGENT_MESSAGING_ENDPOINT
-
A365_AGENT_BLUEPRINT_ID が未設定なら deploy_agent_webapp.py が先に
a365 setup blueprint -n <agent-name> --no-endpoint を実行してから続ける(Step 4 の未実施を自動で補う)。
-
--messaging-endpoint は --endpoint-only との併用が必須。
-
2 つの a365 setup blueprint は a365.generated.config.json があるディレクトリで実行する。
-
エンドポイントは自前 App Service の /api/messages。ここに Foundry の URL を入れない。
-
プランを後から下げるとこの前提が黙って崩れる。受け取り時と不具合調査の入口で
python scripts/provision_selfhost.py --check を通す。
-
runtime: "copilot-sdk" の場合は、デプロイ先でもランタイムの前提を実測する。
子プロセスの起動可否・書込可能パス・送信先の許可はローカルでは再現しない。
python .github/skills/foundry-autopilot/scripts/check_copilot_sdk_env.py --route byok
応答中のターンがあるときは deploy / restart しない。 コンテナが入れ替わると、
実行中のターンは例外も残さず消え、依頼者には何も返らない(チャネルは再送しない)。
資料作成のような長いターンほど当たりやすい。App Insights に
Application started が出た時刻と、依頼者が黙って待たされた時刻が一致したらこれ。
Step 7: 人格と初期品質を入れる
ここからは初回 Build + Deploy 後の個別開発ループ。追加要望を小さく実装し、変更ごとに
python scripts/deploy_ai_teammate.py --check を通してから --execute で再デプロイする。
公開前に 秘書プロンプト雛形 を
prompts/system.md へコピーし、<表示名> / <役割> / <人格> を業務に合わせて置き換える。
設計意図と実装チェックは
references/assistant-agent-pattern.md。
最初のバージョンから最低限これを満たすこと。
- 候補提示後の「お願い」「OK」は承認として扱い、同じターンで書き込みツールを実行する
- ツールを呼ぶ前に「許可されていない」と推測で断らず、実際のエラーだけを失敗として扱う
- Dataverse の HR・面談などを分類名だけで一律拒否せず、まず検索して返った範囲を回答する
- 役割に合う温かい口調を明記し、冷たい選択肢の列挙だけで終わらせない
- 実行結果が
content ではなく structuredContent にある場合も成功としてモデルへ返す
Step 8: 機能ブロックを足す
Step 0 で選んだブロックだけを実装する。手順はすべて
references/feature-blocks.md(テンプレートのコピー →
アプリ設定 → DI 登録 → 再デプロイ)。
| ブロック | 何ができるようになるか | 詳細 |
|---|
| B2 + B6 | エージェント宛のメールを見に行って自分の名前で返信する | feature-blocks.md §1 |
| B9 | Teams チャットを自分から作って送る | §2 |
| B10 | Grounding with Bing で Web を検索・閲覧する | §3 |
| B11 | 決めた時刻に自分から動いて配信する | §4 |
| B12 | Python を実行してファイルを読み書きする | §5 |
| B13 | 長いターンの経過を伝える | §6 |
| B14 | 成果物を台帳で管理し、同意を取ってから共有する | §7 |
| B15 | 誰が・どの処理が・どのツールがいくら使ったかを答える | §8 |
| B16 | Teams で送られたファイルを受け取って作業に使う | §9 |
| B17 | Azure OpenAI で画像を生成し、OneDrive の台帳付き成果物として渡す | §10 |
B15 は役割によらず入れる。 Azure の課金はマネージド ID 1 つでしか集計されず、
人別・処理別・ツール別の内訳は後から復元できない(→ usage-accounting.md)。
インスタンス単位の同意・委任スコープ付与は Step 11。ここではコードと設定だけを入れる。
入口(チャット / メール / 定期実行)ごとに使える能力が変わらないよう、
実行時コンテキストにも能力を明示する(→ outbound-formatting.md §5)。
B2/B6・B9・B10・B12・B14・B16 を足したら、同じ Step で
prompt-injection.md の対策も入れる。
これらは第三者が書いた文章をエージェントに読ませるブロックで、
対策なしだと「メール本文に書いた命令がそのまま実行される」状態になる。
ブロックを足した後で入れると、フェンスの対象漏れに気づけない。
Step 9: Teams アプリパッケージをビルドする
python scripts/build_teams_package.py --require-template
--require-template は A365_AGENT_BLUEPRINT_ID 未設定ならビルドを止める。
未設定のまま公開すると "Agent template" ではない共有エージェントとして登録され、手戻りになる。
- 出力の
app name と color icon 行で、意図した表示名とアイコンが入ったかを必ず確認する。
- 再アップロードのたびに
.env の TEAMS_APP_VERSION を上げる(同一バージョンは拒否される)。
Step 10: M365 管理センターへ公開してインスタンスを作る
devPreview(Agent template)manifest は Microsoft Graph の POST /appCatalogs/teamsApps が
明示的に拒否する(Please use M365 Admin Center.)。M365 管理センターの実測 private API を、
ログイン済み VS Code 統合ブラウザから承認 plan 経由で使う
(→ agent-template-upload.md)。
まず ZIP と対象 tenant を固定した staging plan を作る。plan と hash の確認だけでは変更されない。
python scripts/plan_agent_template_upload.py `
--package "teams/$env:AGENT_NAME-teams-app.zip" `
--tenant-id $env:AZURE_TENANT_ID `
--output .mcp/agent-template-stage-plan.json
- ZIP の SHA-256、manifest ID、version、blueprint ID、tenant ID と
PLAN_HASH を確認して承認する。
- 同じcommandへ
--apply --expected-hash <PLAN_HASH> を加え、READY_FOR_BROWSER_STAGE を確認する。
stageApprovedPackage() をログイン済み統合ブラウザで実行する。runner はbrowser tenantを照合してZIPをstagingし、応答の AppId / MosOperationId を束縛した別の finalize plan と hashを出す。
- finalize plan の
AppId、version、MosOperationId、公開範囲(現contractはAll users、Activate None)を確認し、二度目の明示承認を取る。
finalizeApprovedPackage() を承認hash付きで実行する。runnerは FINALIZEPACKAGE 後に同じTitle ID/versionをread-backする。
- Registry の Agent template から agent instance を作成し、instance ID、service principal、UPN、owner / sponsor を記録する。
- 払い出された agent user に Microsoft 365 Frontier for Autopilot を割り当てる。
Agent 365 のライセンス席は確認・割り当てず、割り当て完了後に採用後設定へ進む。
staging承認はpublish承認を兼ねない。FINALIZEPACKAGE は全ユーザーへの公開なので、Step 0の承認が無い場合は実行しない。
認証、MFA、step-up、consentは自動化せず、利用者がブラウザ上で完了する。
Add agent が表示されない場合は先へ進まない。 AI Administrator の割り当て、
devPreview の場合は管理者自身の Microsoft Copilot ライセンスと Frontier 登録を確認する。
GA スキーマ(非 devPreview)の共有エージェントのみ python scripts/publish_teams_app.py
(管理者ロールが無い場合は --requires-review)で Graph 経由の公開ができる。
Step 11: インスタンス SP に同意とスコープを付与する
Teams で無応答になる最頻出の原因。インスタンスを作り直すたびに必要。
python scripts/grant_agent_instance_consent.py --instance-name "<インスタンス表示名>"
# 機能ブロックが要る委任スコープを付与(B9 / B6 / B14 を入れた場合)
python scripts/grant_agent_graph_scopes.py --instance-id $env:A365_AGENT_INSTANCE_ID
python scripts/grant_agent_graph_scopes.py --instance-id $env:A365_AGENT_INSTANCE_ID --check
az webapp restart -g $env:AZURE_RESOURCE_GROUP -n $env:AGENT_WEBAPP_NAME
付与する委任スコープは User.Read / Chat.Create / Chat.Read / ChatMessage.Send に加え、
B6 なら Mail.Send、B14 なら Files.ReadWrite、B12 のファイル取り込みなら Files.Read.All。
-
ログに出る AADSTS82001 は無視してよい。真因は AADSTS65001
(→ troubleshooting.md #19)。
-
同意も Dataverse 登録もインスタンス単位で、テンプレート更新では引き継がれない。
表示名を変えたつもりで新インスタンスができていると、新 SP は oauth2PermissionGrants が空になり
Teams で完全に沈黙する。まずここを疑う。
az rest --method GET --url "https://graph.microsoft.com/v1.0/servicePrincipals/<インスタンス SP objectId>/oauth2PermissionGrants" --query "value[].{r:resourceId,s:scope}" -o json
-
空配列が返ったら MCP 依存先の同意も入れ直す(Dataverse / Work IQ。
→ agent-brain.md §6-2・§7-1)。Dataverse を使うなら
systemuser 登録 / 許可 MCP クライアント / セキュリティ ロールも新インスタンスでやり直す。
Step 12: 顔写真と Teams プレゼンスを設定する
パッケージのアイコンとプロフィール写真は別物。 写真はプロフィール カード・People ピッカー・
送信メールの差出人アバターに出るが、パッケージのアップロードでは設定されない。
python scripts/set_agent_user_photo.py --upn <インスタンスの UPN>
python scripts/configure_agent_presence.py `
--managed-identity-client-id $env:AZURE_BOT_MSA_APP_ID `
--agent-user-id $env:A365_AGENT_USER_ID `
--resource-group $env:AZURE_RESOURCE_GROUP --webapp $env:AGENT_WEBAPP_NAME
Copy-Item .github/skills/foundry-autopilot/references/templates/PresenceWorker.template.cs `
src/<agent-name>-agent/PresenceWorker.cs
- 写真は Graph が JPEG を要求するので、スクリプトが PNG を 648x648 の JPEG に変換して送る。
必要な権限は
ProfilePhoto.ReadWrite.All または User.ReadWrite.All。
- agentUser は Teams クライアントへサインインしないため、そのままでは Offline(×)が出る。
PresenceWorker が Graph のアプリ プレゼンス セッションを更新し、App Service の稼働を反映する。
heartbeat は起動直後と 2 時間ごと、セッション寿命は 4 時間。
- 再デプロイ後、ログに
Teams presence refreshed for agentic user が出れば成功。
- Teams / Outlook はアバターをキャッシュする。すぐ反映しなくても再送しない。
Step 13: 検証する
az webapp log tail -g $env:AZURE_RESOURCE_GROUP -n $env:AGENT_WEBAPP_NAME
を流したまま Teams でエージェントにメッセージを送り、応答が返ることを確認する。
検証チェックリストを上から確認する。
何も流れてこないときはログ設定が無効になっている。起動時にしか出ないログを取るには
log tail を先に繋いでから restart する必要がある。手順は
references/self-hosted-agent.md 手順 7。
応答が返るようになったら、中身の作り込みは
references/agent-brain.md に従って進める
(ID 面は凍結し、アプリ面だけを回す)。実データを扱わせる場合は同ファイル §6(Dataverse MCP)へ。
同意付与・systemuser 登録・許可 MCP クライアント・セキュリティ ロールの
4 つが揃って初めて通る。どれが欠けても別の 403 になる。
回帰テストと評価を仕込んでから引き渡す。
手で 1 回動かした結果は、次のデプロイでは何も保証しない。
# 1. 回帰テスト(deploy_ai_teammate.py --execute の末尾でも自動実行される)
python scripts/run_regression_tests.py --check # 不変条件だけ(無料・決定的)
python scripts/run_regression_tests.py --execute # 実際に 1 ターン回す
# 2. publish が Foundry の日次 Evaluations も自動構成したことを確認する
python scripts/setup_foundry_evaluation.py --check --mode scheduled
判断材料は regression-tests.md と
foundry-evaluation.md。
終了コード **2 は「測れていない」**であって green ではない。ここを混同すると、
壊れていることにも気づかないまま引き渡すことになる。
CI/CD・レビューゲート・リリース記録は alm スキルへ引き継ぐ。
汎用化と秘匿化
コミットする成果物にテナント固有の値を残さない。
| ルール | 内容 |
|---|
| テンプレートのみコミット | agent.template.yaml / manifest.template.json / agenticUser.template.json を編集し、レンダリング結果(agent.yaml / manifest.json / *.zip)はコミットしない |
実値は ${VAR} | GUID・ARM リソース ID・エンドポイント URL・テナント名・組織名は直書きせず、定義元は references/.env.example 1 か所にする |
| スクリプトに定数を埋めない | 値は argparse 引数 → .env → 環境変数の順に解決する。リソース名は <agent-name> から機械的に導出する |
| 固定値だけ定数化 | 5a807f24-c9de-44ee-a3a7-329e88a00ffc(Messaging Bot API)のような全テナント共通の well-known GUID はスクリプト内の名前付き定数にする(.env に入れない) |
| 秘匿対象 | 置き場所 | 禁止事項 |
|---|
.env(実値) | ローカルのみ | コミット禁止。.env.example だけを共有する |
a365.generated.config.json | ローカルのみ | ブループリントのシークレットを含む。コミット禁止・貼り付け禁止 |
認証キャッシュ(.a365-auth.json / auth-token.json / *token-cache*) | ローカルのみ | リフレッシュトークンを含む。standard の auth_helper.py のキャッシュを使う |
| ブループリントのクライアントシークレット | App Service アプリ設定 Connections__ServiceConnection__Settings__ClientSecret | appsettings.json / テンプレート / ログ / チャットへの出力禁止 |
| CI の Azure 資格情報 | GitHub Actions Secrets / Azure Pipelines 変数グループ / Key Vault | リポジトリ内のファイル禁止 |
.gitignore に必要なのは .env / agents/**/agent.yaml / teams/*.zip / teams/manifest.json /
a365.generated.config*.json / .a365-auth.json / auth-token.json / *token-cache* /
publish/ / publish.zip。
運用ルール:
a365 setup blueprint はシークレットを標準出力に平文で出す。ファイルへリダイレクトしない、
チャットに貼らない、詳細ログを残さない。
az ad app credential reset は必ず --append を付ける(既存資格情報が失効するため)。
取得値は変数で受けて即座にアプリ設定へ渡し、Remove-Variable で破棄する。
- 本格実装では
alm スキルの pre-commit(汎用化 → Secrets 同期 → 漏洩検査)を有効化する。
検証チェックリスト
設計
秘匿化
ID 面(Step 4・6・10・11)
Autopilot の場合は次を確認する(以下の自己ホスト項目で代替しない)。
自己ホストを明示選択した場合のみ:
アプリ面(Step 7・8・13)
回帰テストと評価(Step 13)
プロンプト インジェクション(外部データを読むブロックを入れた場合)