はじめに
Anthropic社が公開したAgent Skills(スキル)は、SKILL.mdを含めたパッケージで、タスクの実施手順やドメイン知識をLLMに与えることができます。大きな特徴として段階的な開示(Progressive disclosure)があり、必要な時に必要な情報だけを読み取ることで、コンテキストの消費を抑えています。現在ではオープンフォーマットとして仕様が公開されており、多くのコーディングエージェントやツールがサポートしています。AIエージェント開発の文脈でも、Google Agent Development Kit(ADK)やStrands Agentsでスキルを取り込む仕組みが提供されています。また、プレビューではありますが、マネージドなエージェント実行環境であるAWSのAgentCore Harnessでもスキルと簡単に接続できるようになっています。
スキルとツール
本記事では、スキルを「LLMに与える作業手順やドメイン知識」、ツールを「AIエージェントが外部と相互作用するための操作」として扱います。スキルとツールは相互補完の関係にあり、スキルは、作業手順やドメイン知識を通じて、どのような場面で、どのツールを、どの順序で使うべきかをLLMに伝える役割を持ちます。
AIエージェントにおけるスキル評価
利用用途が拡大しているスキルですが、作成、評価、改善提案はAnthropicが公開しているskill-creatorを使うことで効率よくできます。一方で、AIエージェントの一部分としてスキルを考えたとき、
- どのスキルを、いつ読み込んだか
- 読み込んだスキルを適切に実行できたか
- AIエージェントの最終結果は適切か
を考慮する必要があると考えました。そこでスキルをAIエージェントに組み込む際にどのような評価をするべきかを考えてみました。
AIエージェントの評価では、以前から最終回答を評価する方法や、ツールの実行履歴である軌跡を確認する方法などがありました。今回の方法もそれらに近いものです。一方で、新たにスキルという構成要素を取り入れる際には、スキルを評価単位として切り出すことで、問題がスキルの読み込み条件にあるのか、SKILL.mdの記述にあるのか、AIエージェント全体にあるのかを整理しやすくなります。この記事では、スキルを組み込んだAIエージェントの評価改善の取り組みをSkillOpsと呼ぶことにします。
評価内容や実施方法などは従来のLLMOpsと変わらない点が多いですが、スキルの評価改善をターゲットとしていることからSkillOpsと定義しています。
スキルの評価指標
スキルの評価軸として、今回は次の3つを考えます
- スキルトリガー(Skill Trigger)
- スキル実行(Skill Execution)
- 最終回答(Final Response)
先にまとめると、評価観点と評価結果が思わしくないときに改善すべき場所は表のとおりです。
| 評価軸 | 観点 | 改善すべき場所 |
|---|---|---|
| スキルトリガー | スキルが適したタイミングで読み込まれたか | SKILL.mdのフロントマター |
| スキル実行 | スキルに従った動作ができているか | SKILL.mdの中身 |
| 最終回答 | AIエージェントが期待した回答ができているか | スキルを含むAIエージェント全体 |
スキルトリガー
AIエージェントが適切なスキルを適切な順番で読み込んだかを評価します。スキルはどのようなときに読み込むべきかをSKILL.mdのフロントマターに記載します。これが不明確であると、適切な場面でスキルが読み込まれない、別のスキルが読み込まれるなど問題が発生します。
この評価軸によって、スキルのフロントマターが適切か、AIエージェントが類似したスキルやツールを持ちすぎていないかを判断できます。
評価方法としては、期待するスキルのリストを事前定義し、それとAIエージェントの動作履歴を比較します。今回は、期待するスキルが、期待した順序で、抜け漏れなく読み込まれていればPASSとします。前後や途中に余分なスキルは挟まっても許容します。余分なスキル読み込みを許容するかは、AIエージェントの有する機能次第でもあります。今後この辺りは検討したいです。
図の例では、期待と動作は、
- スキルαを読み込む
これに対して、実際の動作は
- スキルαを読み込む
- スキルβを読み込む
となっています。期待したスキルαは問題なく読み込まれているので、評価としてはPASSとなります。余分なスキルβも読み込まれていますが、前述の通り今回の評価方法ではこれを許容します。
スキル実行
スキルを読み込んだ後、AIエージェントがそのスキルの指示に従って正しく動作したかを評価します。例えばスキルに、具体的な作業手順が明示されている場合、その指示に従って適切なツールを適切な順序で呼び出したかを確認します。
スキルでの指示内容が明確であるか、指示内容を実施できる環境をAIエージェントが持っているかを確認できます。
評価対象となるスキルが読み込まれた後に実行したツールが期待したツールリストと一致するかを確認します。比較対象はターゲットスキルの読み込み直後から最終回答までで、今回は完全一致のみをPASSとします。比較対象もツール名のみとしています。引数などもチェックするなど拡張の余地はあります。
図の例では、スキルαの読み込みを起点として、ツール実行履歴を比較しています。期待と実際の動作に差異があるため、今回の評価方法ではPASSとはなりません。
最終回答
AIエージェントの最終回答が、期待した内容であるか評価します。これはスキルそのものの評価ではなく、AIエージェント全体の評価の位置づけです。
評価は実際の最終出力と期待する回答内容とをLLM-as-a-Judgeで評価します。内容が一致していればPASSとします。評価プロンプトは事前に準備しておきます。
SkillOpsを試してみる
実際にAIエージェントを動作させ、先ほど紹介した評価指標を実際に試してみました。以下の手順で実施しました。
- AIエージェントの構築
- AIエージェントの実行
- AIエージェントの動作結果取得
- 期待動作データの定義
- 3つの指標での評価
- (問題が見つかれば)改善
1. AIエージェントの構築
今回の評価対象となるAIエージェントを紹介します。今回はAmazon Bedrock AgentCore Harness上に1つのMCPサーバーと2つのスキルを接続したAIエージェントを用意しました。
利用可能なMCPサーバー
検索エンジンであるTavilyを用いて、Web検索を行うMCPサーバーです。Tavilyが提供する公式のリモートMCPサーバーを利用しています。
https://docs.tavily.com/documentation/mcp
利用可能なスキル
「レポート作成スキル」と「会議メモ作成スキル」の2つを提供しています。実際に利用したスキルはGitHubを参照してください。
レポート作成スキル
Web検索結果をまとめ、レポートとして保存する作業手順を記載したスキルです。指示として以下の手順を記載しています。
- Web検索し、ユーザーリクエストに応じた情報を収集する
- 結果を要約し、Markdown形式にする
- ローカルファイルシステムに保存する
- 保存したファイルのSHA-256を取得する
- レスポンスとして、保存ファイルパスとSHA-256ハッシュを返す
会議メモ作成スキル
会議メモのテンプレートを定義したスキルです。受け取った内容をテンプレートに則した形式に変換します。今回のテストケースで呼び出されることはありませんが、複数のスキルを用意することで、スキルトリガー評価に意味を持たせています。
2. AIエージェントの実行
構築したAIエージェントをテスト実行します。ユーザープロンプトとして、以下を入力します。
Agent Skillsに関する調査レポートを作成してください
これはレポート作成スキルが読み込まれることを期待したもので、AIエージェント全体の期待するツール実行は以下となります。
3. AIエージェントの動作結果取得
AIエージェントの動作結果を取得します。評価では、どのスキルを読み込んだか、どのツールを実行したかといったトレースが必要となります。
CloudWatch Logsから該当するAIエージェントの構造化ログを/aws/bedrock-agentcore/runtimes/<agent_id>-<endpoint_name>/otel-rt-logsから取得し、評価しやすいように整理しています。評価にはツール実行のみが必要なため、間にあるLLM呼び出しは無視しています。スクリプト詳細はGitHubを参照してください(observer.py)。
AgentCoreから取得できるトレースやログなどは以下の公式ドキュメントを参考にしてください。
https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-view.html
4. 期待動作データの定義
評価する前に、期待するデータ(正解データ)を定義します。今回はJSON形式で以下のように定義しています。
{
"test_cases": [
{
"id": "web-research-report-basic",
"target_skill": "web-research-report",
"trigger": {
"expected_skill_sequence": [
"web-research-report"
]
},
"execution": {
"expected_tools": [
"mcp_1_tavily_search",
"file_operations",
"shell"
]
},
"final_response": {
"expected_output": "最終回答には、調査レポートの作成が完了したこと、レポートファイルのパス、SHA-256ハッシュが含まれていること。",
"evaluation_criteria": "最終回答がユーザーにとって有用であり、生成したレポートファイルの場所とSHA-256ハッシュを明確に示しているかを評価する。必要に応じて、調査結果の要約が簡潔に含まれていることも評価する。"
}
}
]
}
各評価指標で参照する属性名とその概要は以下の通りです。
| 評価指標 | 属性名 | 概要 |
|---|---|---|
| スキルトリガー | trigger | expected_skill_sequenceで、期待するスキルリストを定義 |
| スキル実行 | execution | expected_toolsで、スキル読み込み時に期待する動作をリストで定義 |
| 最終回答 | final_response | expected_outputで、期待する回答の内容を、evaluation_criteriaで評価基準を定義 |
5. 3つの指標での評価
ステップ3で取得した動作結果とステップ4で定義した期待動作を照らし合わせて評価します。評価はPythonスクリプト(eval.py)で実行し、評価結果はJSON形式で出力しています。
{
<中略>
"summary": {
"evaluation_count": 1,
"quality": {
"trigger": {
"pass": 1,
"fail": 0,
"skipped": 0
},
"execution": {
"pass": 0,
"fail": 1,
"skipped": 0
},
"final_response": {
"pass": 1,
"fail": 0,
"skipped": 0
}
}
},
<中略>
}
評価が合格であればPASS、不合格であればFAILとなります。skippedは評価未実施の際にカウントします。今回は期待したスキルが読み込まれた場合のみスキル実行と最終回答を評価するように実装しているため、仮に期待したスキルが読み込まれなかった場合は、skippedとなります。final_responseについては、今回はスキルに焦点を当てているため、スキルが読み込まれなかった際は評価自体をスキップしていますが、AIエージェントそのものの評価という観点では常に評価するのがよいでしょう。
6. 改善
評価結果をもとに改善の必要可否、改善対象を判断し、スキルの改善を実施します。
SkillOpsを実施した所感
今回作成したSkillOpsを実施することに意味があるかについてですが、一定の効果はあるのではないかと思います。理由として今回の取り組みを試す際に、思った通りにAIエージェントが動作せず、実際にスキルの記載に2つの改良箇所が見つかったためです。
ケース1. レポートの作成場所
はじめのSKILL.mdに記載した手順は以下のようになっていました。
<中略>
## Procedure
1. Use the web search tool to search for the requested topic.
2. Summarize the findings into a markdown report.
3. Use file_operations to write the report to:
/tmp/web-research-report/report.md
4. Use shell to calculate the SHA-256 hash:
sha256sum /tmp/web-research-report/report.md
5. In the final response, include:
- report path
- SHA-256 hash
Do not fabricate sources. If web search fails, clearly report the failure.
この手順では、ファイルの作成場所が**/tmp/web-research-report/report.md**となっています。この親ディレクトリが実行環境には存在しないため、レポート作成前にmkdirでディレクトリ作成が実施されていました。ファイルシステム操作は実行環境の状況によっても変わるので、実環境でテストしたからこそ気が付けたことでした。
なお、SKILL.mdのファイルパスを./report.md と修正することで、ディレクトリ作成処理を回避できました。
ケース2. 誤ったMCPツールの利用
スキルで指示した手順では、Web検索ツールを使ってレポート生成を指示しています。今回利用したTavilyのMCPサーバーでは、searchとresearchというツールが提供されています。searchは単純なWeb検索で、researchは非同期タスクとしてWeb検索に加えてレポート生成まで実施します。
期待動作は、
- searchによるWeb検索→LLMによるレポート生成
でしたが、実際は
- researchによるWeb検索とレポート生成
となっていました。SKILL.mdの手順を「単純な検索のみを行うこと」「レポートの様式を明確にすること」とすることで、期待動作になりました。
なお、今回の2つのケースはいずれも「スキル実行」の評価でNGとなっています。そのため、スキルの記述内容に改善余地があると判断し、SKILL.md内の記載を変更しています。どの評価項目でNGがでたか、によって改善対象を絞りやすくなるのもメリットと考えています。
また、今回は「スキル実行」の評価で完全一致による比較を採用しました。動作が分岐するようなスキルの場合は、部分一致などに比較方法を変更するとよいでしょう。
まとめ
今回はAIエージェントに組み込むスキルの評価、改善に向けてSkillOpsを定義し、実践しました。複数の評価軸を用意することで、評価結果に応じて改善すべき場所を素早く特定することができました。
スキル内部を評価する「スキル実行」では、ツール実行履歴の単純な比較のみを実施しました。一方でスキルは、作業手順指示だけではなく、ドメイン知識を渡すなど様々な用途で使用されるため、それに応じた評価指標も必要になると考えています。
利用したコードやスキルは以下のGitHubを参照ください。またコードは生成AIを活用して実装しています。実行される前には内容を確認してください。
https://github.com/licux/skillops







