
AWS DevOps Agent のスキルを GitHub リポジトリからインポートしてみた
こんにちは、製造ビジネステクノロジー部の若槻です。
AWS DevOps Agent のスキルは、Operator Web App のフォームで直接作成するほかに、GitHub リポジトリのディレクトリ URL を指定してインポートすることもできます。スキルを Git で版管理できるので、こちらのほうが運用しやすそうです。
ただこの機能を使うにあたって、GitHub 連携の要件が気になりました。以前 DevOps Agent に修正プルリクエストを作らせた際は、ネイティブの GitHub 連携では権限が足りず GitHub MCP サーバーの接続が必要でした。今回はどちらが必要なのでしょうか。
そこで、自作スキルを実際にインポートしつつ、同一内容のスキルを 3 つのリポジトリに置いて連携要件を検証してみました。
結論
- リポジトリインポートには ネイティブの GitHub 連携が必須です。GitHub MCP サーバーを接続していても代替できません
- プライベートリポジトリの場合、連携している GitHub アカウントがそのリポジトリへの read 権限を持っている必要があります。GitHub App のインストール対象に含まれていないリポジトリはインポートに失敗します
- パブリックリポジトリなら、GitHub App のインストール対象外でもインポートできます。何らかの GitHub アカウントが Agent Space に関連付けられていれば十分です
- インポートしたスキルは名前・説明・指示がすべて読み取り専用になります。更新はリポジトリ側を編集して明示的に「同期」を実行する必要があり、自動反映はされません
references/配下のファイルもディレクトリごと取り込まれ、エージェントは実際にそれを読み込んで回答します- スキルのパスに日本語が含まれるとインポートできません。ディレクトリ名だけでなく、
references/配下のファイル名が日本語の場合もInternal Server Errorになります。ファイルの中身が日本語であることは問題ありません
なぜネイティブ連携が必要なのか
ドキュメントの前提条件に明記されています。
A GitHub account associated with your Agent Space. To connect a GitHub account, see Connecting GitHub. Any GitHub account connection enables importing from public repositories. For private repositories, the associated account must have read access to the repository.
これは構造的な理由があります。リポジトリインポートは「エージェントが会話中にツールを呼ぶ」処理ではなく、サービス側が GitHub App の資格情報でディレクトリを取得するアセット管理操作(CreateAsset の content.sourceUrl)です。MCP サーバーのツールはエージェントの実行時にしか渡らないため、この経路には一切関与しません。
検証に使ったスキル
自分のプライベートリポジトリ security-infra に、そのリポジトリ自身の構成を説明するスキルを作成しました。AWS のセキュリティ検出基盤を AWS CDK で管理しているリポジトリなので、「どのサービスがどのコンストラクトで定義されているか」をエージェントに教えるスキルです。
ディレクトリ構成は次のとおりです。references/ を含む複数ファイル構成にして、ディレクトリごと取り込まれるかも確認できるようにしました。
skills/security-infra-guardrails/
├── SKILL.md
└── references/
└── construct-map.md
SKILL.md は frontmatter に name と description が必須です。この 2 つはインポート時にサービス側が読み取ってスキルの名前と説明になります。
---
name: security-infra-guardrails
description: security-infra リポジトリで管理している AWS セキュリティ検出基盤(GuardDuty / Security Hub / Inspector / Macie / Detective / AWS Config / VPC フローログ)の構成と調査手順。セキュリティ検出サービスの有効状態や設定を確認したいとき、検出結果の調査でどのサービスを参照すべきか判断したいとき、該当設定を定義している AWS CDK コードの場所を特定したいときに使用する。
---
# security-infra ガードレール調査
security-infra リポジトリは、AWS アカウントのセキュリティ検出基盤を AWS CDK で管理している。セキュリティ検出サービスの設定に関する調査では、このスキルの手順に従うこと。
## 前提となる構成
- 検出サービスは 2 リージョンに展開している
- `ap-northeast-1`: CloudFormation スタック `Security`。Security Hub の集約リージョン
- `us-east-1`: CloudFormation スタック `SecurityVirginia`。集約先ではない
- 各サービスは `lib/constructs/` 配下のカスタムコンストラクトで有効化している
- Macie・VPC フローログ・IAM グループなど一部のリソースは `ap-northeast-1` にのみ存在する
サービスとコードの対応は `references/construct-map.md` を参照すること。
## ステップ 1: 対象リージョンとスタックを特定する
調査対象のリソースが属するリージョンを確認し、対応するスタックを決める。
- `ap-northeast-1` → `Security` スタック
- `us-east-1` → `SecurityVirginia` スタック
リージョンが特定できない場合は、Security Hub の集約リージョンである `ap-northeast-1` から調べる。
## ステップ 2: 検出サービスの有効状態を確認する
対象リージョンで、調査に関係する検出サービスが有効になっているかを確認する。両リージョンに存在するサービスは、片方だけ設定がずれていないかも確認する。
## ステップ 3: 設定を定義しているコードを特定する
`references/construct-map.md` の対応表から、該当サービスのコンストラクトのファイルパスを特定する。コンストラクトの実装と、それを呼び出しているスタック(`lib/security-stack.ts` または `lib/security-sub-region-stack.ts`)の両方を読むこと。
環境ごとに変わる値は `bin/parameter.ts` に定義されているため、設定値が想定と異なる場合はこのファイルも確認する。
## ステップ 4: 報告する
以下を含めて報告する。
1. 対象リージョンとスタック名
2. 検出サービスの有効状態と、確認した設定値
3. 設定を定義しているコードのファイルパス
4. 設定に問題がある場合は、修正すべきコードの箇所と修正方針
設定変更を提案する場合は、`ap-northeast-1` と `us-east-1` のどちらに影響するかを必ず明記すること。
references/construct-map.md は、サービスとコンストラクトのファイルパスの対応表です。
# コンストラクト対応表
security-infra リポジトリで管理しているセキュリティ検出サービスと、それを定義している AWS CDK コンストラクトの対応表。
## 検出・監査サービス
| サービス | コンストラクトのパス | `Security`<br>(ap-northeast-1) | `SecurityVirginia`<br>(us-east-1) |
|---|---|---|---|
| Amazon GuardDuty | `lib/constructs/guard-duty/index.ts` | あり | あり |
| AWS Security Hub | `lib/constructs/security-hub/index.ts` | あり(集約リージョン) | あり |
| Amazon Inspector | `lib/constructs/inspector/index.ts` | あり | あり |
| Amazon Detective | `lib/constructs/detective/index.ts` | あり | あり |
| AWS Config | `lib/constructs/aws-config/index.ts` | あり | あり |
| Amazon Macie | `lib/constructs/macie/index.ts` | あり | なし |
| VPC フローログ | `lib/constructs/vpc-flow-logs/index.ts` | あり | なし |
## ガードレール設定
| 設定 | コンストラクトのパス | `Security`<br>(ap-northeast-1) | `SecurityVirginia`<br>(us-east-1) |
|---|---|---|---|
| EBS 暗号化のデフォルト有効化 | `lib/constructs/ebs-encryption/index.ts` | あり | あり |
| VPC Block Public Access | `lib/constructs/vpc-public-block-access/index.ts` | あり | あり |
| S3 アカウントレベルのパブリックアクセスブロック | `lib/constructs/s3-account-public-access-block/index.ts` | あり | なし |
| IAM アカウントパスワードポリシー | `lib/constructs/account-password-policy/index.ts` | あり | なし |
## ログ保管先
| リソース | コンストラクトのパス | `Security`<br>(ap-northeast-1) | `SecurityVirginia`<br>(us-east-1) |
|---|---|---|---|
| ログ保管先バケット | `lib/constructs/log-destination-bucket/index.ts` | あり | あり |
| サーバーアクセスログ保管先バケット | `lib/constructs/server-access-logging-destination-bucket/index.ts` | あり | あり |
| CloudFormation テンプレート用バケット | `lib/constructs/cf-templates-bucket/index.ts` | あり | なし |
## 権限・連携
| リソース | コンストラクトのパス | `Security`<br>(ap-northeast-1) | `SecurityVirginia`<br>(us-east-1) |
|---|---|---|---|
| AWS DevOps Agent | `lib/constructs/devops-agent/index.ts` | あり | なし |
| CI/CD 用権限 | `lib/constructs/cicd-permission/index.ts` | あり | あり |
| GitHub Actions OIDC プロバイダー | `lib/constructs/github-actions-oidc-provider/index.ts` | あり | なし |
| IAM グループ | `lib/constructs/iam-group/index.ts` | あり | なし |
| API Gateway のログ出力権限 | `lib/constructs/api-gateway-logging-permission/index.ts` | あり | なし |
## 呼び出し元
| ファイル | 役割 |
|---|---|
| `bin/iac.ts` | スタックの定義とリージョンの割り当て |
| `bin/parameter.ts` | 環境ごとのパラメーター |
| `lib/security-stack.ts` | `ap-northeast-1` の `Security` スタック |
| `lib/security-sub-region-stack.ts` | `us-east-1` の `SecurityVirginia` スタック |
インポートしてみる
Operator Web App の ナレッジ ページの スキル タブから スキルを追加 を選び、リポジトリからインポート を選択します。
入力するのは GitHub のディレクトリ URL、ステータス、エージェントタイプの 3 つだけです。名前と説明は SKILL.md の frontmatter から読み取られるため入力欄がありません。

リポジトリからインポートのフォーム。名前と説明の入力欄がない
スキルをインポートする を押すと、すぐにカスタムスキルの一覧に追加されました。プライベートリポジトリですが問題なく取り込めています。
詳細画面を開くと、SKILL.md だけでなく references/construct-map.md もディレクトリごと取り込まれていることが分かります。

名前・説明・指示のすべてに「読み取り専用」バッジが付いている
インポートしたスキルの特徴が詳細画面によく出ています。
- タイトル横に GitHub から同期済み バッジが付く
- 名前・説明・指示 がすべて 読み取り専用。「SKILL.md を次の場所に保存: GitHub。更新するには、ソースファイルを編集して同期します。」と案内される
- 編集できるのは ステータス と エージェントタイプ のみ
- 最終同期 の日時とソースリポジトリへのリンクが表示される
- 同期 と ダウンロード ボタンがある
UI のフォームで作成したスキルは本文をその場で編集できますが、インポートしたスキルはリポジトリが正になるわけです。運用としてはこちらのほうが素直だと思います。
本当にネイティブ連携が必要なのか検証する
ドキュメントの記述を実挙動で確かめます。同一内容の SKILL.md を 3 つのリポジトリに置き、GitHub App の許可有無だけを変数にして比較しました。
この Agent Space のネイティブ GitHub 連携は、GitHub App のインストール対象を Only select repositories で security-infra の 1 つだけに絞っています。
| リポジトリ | 公開範囲 | GitHub App の許可 | 結果 |
|---|---|---|---|
security-infra |
private | あり | 成功 |
test |
private | なし | 失敗 |
test-public |
public | なし | 成功 |
許可していないプライベートリポジトリを指定すると、次のエラーになりました。

GitHub 連携がそのリポジトリにアクセスできるか確認せよ、というエラー
スキルのインポートに失敗しました: GitHub repository or path not found. Verify the URL and that your GitHub connection has access to it.
「your GitHub connection has access to it」と、ネイティブ連携のアクセス範囲が直接効いていることが明示されています。SKILL.md の内容は成功したケースと完全に同一なので、差分は GitHub App の許可有無だけです。
一方、パブリックリポジトリは GitHub App の許可対象外でもインポートできました。ドキュメントの「Any GitHub account connection enables importing from public repositories」のとおりです。
なお、この Agent Space には以前の検証で GitHub MCP サーバーも接続してありますが、それによってインポートが通ることはありませんでした。MCP は無関係です。
リポジトリを更新しても自動反映されない
スキルの SKILL.md にステップを 1 つ追加してリポジトリに push し、Web App 側を確認しました。
+## ステップ 4: 検出結果の重複を確認する
+
+Security Hub は `ap-northeast-1` に集約しているため、`us-east-1` で発生した検出結果も `ap-northeast-1` 側に現れる。同じ事象を二重に報告しないよう、検出結果の発生元リージョンを確認すること。
+
-## ステップ 4: 報告する
+## ステップ 5: 報告する
push した直後に詳細画面を開いても、指示の内容は古いままで最終同期の日時も変わりませんでした。
同期 ボタンを押すと内容が更新され、最終同期が 2026/8/6 13:59:47 から 2026/8/6 14:14:13 に進みました。GitHub 側の変更を自動追従する仕組みではないので、リポジトリを更新したら同期を忘れないようにする必要があります。
同期の挙動として、コンテンツはリポジトリの現在の状態で完全に置き換えられます。一方で編集可能な項目(ステータス、エージェントタイプ)は保持されます。
エージェントは参照ファイルまで読み込む
references/ が飾りになっていないか確認するため、対応表を見ないと答えられない質問を投げました。
security-infra リポジトリで管理しているセキュリティ検出サービスのうち、us-east-1 のスタックには含まれていないものはどれですか。それぞれ設定を定義しているコードのファイルパスも教えてください。
エージェントはまず「security-infra-guardrails スキルを読み込んで調べます。」と宣言し、続けて construct-map.md をスキルリソースとして読み込みました。

「Loading a skill」に続いて「Reading a skill resource」が実行されている
回答も対応表どおり、us-east-1 に存在しない検出サービスは Amazon Macie と VPC フローログの 2 つ、ファイルパスも正確でした。SKILL.md だけでなく参照ファイルまで含めて活用されることが確認できました。
パスに日本語が含まれるとインポートできない
スキルのパスに日本語が含まれていると上手くインポートできないことがあったため、条件を分けて検証しました。結果として、ディレクトリ名でもファイル名でも、日本語が含まれるとインポートできませんでした。
| # | 日本語を含む箇所 | URL の指定形式 | 結果 |
|---|---|---|---|
| A | ディレクトリ名 | 日本語のまま | クライアント側のバリデーションで拒否 |
| B | ディレクトリ名 | パーセントエンコード | サーバー側で「パスが見つからない」エラー |
| C | 参照ファイル名(ディレクトリ名は ASCII) | ASCII のみ | Internal Server Error |
| D | なし(C の参照ファイル名を ASCII にしたもの) | ASCII のみ | 成功 |
A: ディレクトリ名に日本語、URL は日本語のまま
skills/日本語ディレクトリ検証/SKILL.md を用意し、GitHub のディレクトリ URL をそのまま貼り付けました。
https://github.com/<owner>/<repo>/tree/main/skills/日本語ディレクトリ検証
この場合は API に届く前にクライアント側のバリデーションで弾かれます。URL の入力欄が赤くなり、インポートボタンも押せなくなります。

「URL は有効な GitHub ディレクトリリンクである必要があります」と表示され、ボタンが無効化される
URL は有効な GitHub ディレクトリリンクである必要があります
URL の形式チェックが ASCII しか通さない実装になっているようです。
B: ディレクトリ名に日本語、URL はパーセントエンコード
ブラウザのアドレスバーからコピーしたときの形式、つまりパーセントエンコードした URL でも試しました。
https://github.com/<owner>/<repo>/tree/main/skills/%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A4%9C%E8%A8%BC
こちらはクライアント側のバリデーションは通過しますが、サーバー側で失敗しました。
スキルのインポートに失敗しました: The specified path was not found in the repository (or is empty). Verify the URL points to a directory containing a SKILL.md.
GitHub 上には確かに存在するディレクトリなので、サーバー側でパスのパーセントデコードが行われていないと考えられます。エンコードすればバリデーションは避けられるものの、結局取得はできません。
C: 参照ファイル名だけが日本語
ここが一番厄介でした。ディレクトリ名は ASCII のままで、references/ 配下のファイル名だけを日本語にしたケースです。
skills/japanese-reference-filename/
├── SKILL.md
└── references/
└── 対応表.md
URL に日本語は一切含まれないためバリデーションは通り、リクエストも飛びます。しかし結果は Internal Server Error でした。2 回試して同じ結果です。

エラーの内容が Internal Server Error だけで、原因の手がかりがない
スキルのインポートに失敗しました: Internal Server Error
A や B は「URL が悪い」と分かるメッセージですが、こちらは原因を示す情報がありません。URL は正しくディレクトリを指していて SKILL.md も存在するため、参照ファイル名が原因だと気付くのが難しいのが厄介なところです。
D: 対照ケース
原因を切り分けるため、C と同一の SKILL.md で参照ファイル名だけを ASCII にしたスキルを用意しました。
skills/ascii-reference-filename/
├── SKILL.md
└── references/
└── reference-table.md
こちらは問題なくインポートできました。SKILL.md の本文は参照先のファイル名以外まったく同じなので、日本語のファイル名そのものが原因と確定できます。
対策
スキルのディレクトリ名・ファイル名はすべて ASCII にしておくのが無難です。SKILL.md や参照ファイルの中身が日本語であることは問題なく、実際に今回インポートしたスキルは本文がすべて日本語です。制約はあくまでパスだけです。
frontmatter の name はもともと「小文字の英数字とハイフンのみ」という制約があるため、ディレクトリ名を name に揃えておけば自然と ASCII になります。忘れやすいのは references/ と assets/ 配下のファイル名なので、こちらを意識しておくとよさそうです。
前回の検証とは必要な連携が真逆だった
以前 DevOps Agent に修正プルリクエストを作らせた検証では、ネイティブ連携をアクセスレベル「読み取りと書き込み」で登録してもエージェントに渡る GitHub ツールは読み取り専用の 14 個だけで、プルリクエストを作らせるには GitHub MCP サーバーの接続が必要でした。
今回のスキルインポートはその逆で、ネイティブ連携が必須で MCP では代替できません。
| 用途 | ネイティブ GitHub 連携 | GitHub MCP サーバー |
|---|---|---|
| ソースコードを読む | 必要 | 不要 |
| 修正プルリクエストを作る | 不十分(読み取り専用ツールのみ) | 必要 |
| スキルをリポジトリからインポートする | 必要 | 代替不可 |
「どちらか一方あれば済む」ものではなく、やりたいことによって必要な連携が変わるという理解が要ります。
その他に気付いたこと
制約
ドキュメントに記載されている制約は次のとおりです。
- GitHub URL のみ。
treeを含むディレクトリ URL を指定するとディレクトリ全体が取り込まれます。SKILL.mdがリポジトリ直下にある場合はblobを含むファイル URL も指定できますが、その場合はSKILL.mdのみが取り込まれます - frontmatter 付きの
SKILL.mdが必須 - ディレクトリ全体で 6 MB 以内、最大 100 ファイル
加えて、ドキュメントには記載がありませんが、前述のとおりパスに日本語を含められないという制約もありました。
同名スキルを重複登録できてしまう
パブリックリポジトリの検証時に気付いたのですが、name が同一のスキルを別のリポジトリからインポートすると、エラーにならず 2 件並んで登録されます。一意性のチェックはかかっていないようです。取り違えの原因になりそうなので、一覧のソースリポジトリのリンクで見分ける必要があります。
AWS CLI からも実行できるが、コマンドがまだ入っていなかった
アセット管理の API を使えば、インポートも同期も CLI や SDK から実行できます。
aws devops-agent create-asset \
--agent-space-id <agent-space-id> \
--asset-type skill \
--metadata '{ "agent_types": ["GENERIC"] }' \
--content '{"sourceUrl": {"url": "https://github.com/<owner>/<repo>/tree/main/skills/<skill-name>"}}'
ただ手元の aws-cli 2.34.35 では aws devops-agent に create-asset などのアセット系サブコマンドがまだ含まれておらず、実行できませんでした。CLI から扱いたい場合は先にバージョンを確認したほうがよさそうです。
サンプルスキルもインポートで試せる
AWS が公開している aws-samples/sample-devops-agent-tools の skills/ 配下には、AWS Health イベントの調査や RDS・EKS のオペレーションレビューなどのスキルが置かれています。パブリックリポジトリなので、ディレクトリ URL をそのまま貼り付けてインポートできます。自作する前の下敷きとして使えそうです。
おわりに
AWS DevOps Agent のスキルを GitHub リポジトリからインポートしてみました。
スキルを Git で版管理できるうえに、インポート後は読み取り専用でリポジトリが正になるため、UI で直接作るよりも運用の見通しが良いと感じました。同期が手動なのは注意点ですが、レビューを通したものだけを反映できると考えれば妥当なところだと思います。
連携要件については、ネイティブ GitHub 連携が必須で、プライベートリポジトリでは GitHub App のインストール対象に含めておく必要がある、という点を押さえておけば迷わないはずです。
つまずきやすいのはパスの日本語です。参照ファイル名が日本語だとエラーが Internal Server Error だけで原因が分からないので、インポートが通らないときはまずパスに日本語が混ざっていないかを確認するとよいと思います。
以上




