Cookbook
Agents & skills · for AI agents

必要に応じて読み込むスキルの作成

モデルが関連する際にのみ取得する機能をパッケージ化し、エージェントにアタッチします。

MCP tools:list_skillscreate_skillupdate_agenttest_skill_trigger

原則 — スキルの数を少なく保つ。 エージェントの業務に必要なもののみをアタッチする(約5つ以下)。モデルは1行の description からスキルを選択します。アタッチする数が増えるほど、間違ったスキルやどのスキルも読み込まれる頻度が高くなります。 いつ 使用するかの重複がある場合は、スキルをマージしてください。詳細は 設計原則 を参照してください。

スキル はオンデマンドで読み込まれる機能パックです:システムプロンプトには description(「いつ使用するべきか」)のみが含まれ、モデルはスキルの関連性を判断した場合にのみ、完全な instructions を取得します。したがって、description は短く、いつ を示すものでなければなりません。さもないと、モデルはそれにアクセスすべきかどうかを知りません。

list_skills()                                # what already exists
 
create_skill(
  name="refund-policy",
  description="Use when the user asks about refunds, cancellations or chargebacks.",
  instructions="The full procedure: eligibility windows, how to word the outcome, when to escalate …",
)
 
update_agent(name="Support", add_skills=["refund-policy"])   # attach it (incremental — keeps existing skills)

手順はエージェントの soul(プロンプトの一部であり、すべてのターンで存在する)ではなく、instructions(読み込み時に取得される)に記述してください。いつ を示す1行の description が、スキルを発見可能にするものです。曖昧な description では、モデルはそれを取得しません。

ツールはスキルに同乗できる

スキルは独自のツールバインディングを保持できます — create_skill(tools=[…]) または update_skill(name, add_tools=[…]) を使用することで、手順と必要なツールを1回の操作でアタッチし、自己完結型の機能として提供できます。

スキルのツールは、スキルが読み込まれた後にのみ利用可能になります。 開始時のツールセットには含まれておらず、スキルを読み込むことでそこに追加されます。したがって、順序は固定されています:手順を読み、次にツールを取得する — モデルはツールに飛び越えて即興で処理することはできません。

この順序はプロンプトで要求するのではなく、コードで強制されます。プロンプトで要求しても機能しなかったためです。2026-08-22 に測定したところ、「企業 X の競合他社を調査する」というタスクで、手順とツールを同時に渡した場合、モデルはウェブ検索を3回呼び出し、スキルを全く読み込みませんでした。モデルは記憶から競合他社の名前を捏造し、その捏造された名前で検索して何も見つからず(それらは存在しません)、捏造された名前を回答として記載しました — 手順のステップ1で「まず、この企業が実際に何を販売しているかを確立する」と書かれていたにもかかわらず、その手順は読みませんでした。任意の手順は読み込まれません。

これに依存する前に知っておくべき2つの事項:

  • スキルのツールは、エージェント自身の tools リストには表示されません。 get_agent はエージェントに直接アタッチされたツールのみを表示します。コンソールの [Tools] タブでは、スキルにバインドされたツールは「via skills」という別の読み取り専用行として表示されます。「ツール X が有効かどうか」を確認する場合は、両方の場所を確認するか、テストチャットでツールを呼び出すだけです。
  • エージェントが既に持っているツールは影響を受けません。 エージェント自体が web_search を持っている場合、それはすべてのターンで利用可能であり続けます。スキルに起因して追加されるツールのみが、そのスキルの読み込みを待ちます。
  • ツールを スキル にバインドするのは、その手順内でのみ意味をなす場合(返金スキルの内部での返金照会)です。 エージェント にバインドするのは、ターン全体で一般的に有用な場合(save_contactweb_search)です。

ツールのバインディングは可用性であり、ポリシーではない — 呼び出すべきタイミングは手順に記述する

スキル(またはエージェント)でツールをチェックすることは、そのツールを 呼び出し可能 にするだけです。モデルはスキーマと1行の description をすべてのターンで確認するため、機会主義的に使用することがあります — 訪問者がメールアドレスを申し出ると、save_contact が実行されます。しかし、確実に発生する必要がある動作はすべて書き留める必要があり、その各部分には適切な配置場所が1つあります:

指定する内容配置場所
このスキルを読み込むタイミングスキルの description (すべてのターンでプロンプトに含まれる)
手順:どのステップでどのツールをどの引数で呼び出すかスキルの instructionsツール名を明示する(「発注者が興味を確認した後、メールと電話番号で save_contact を呼び出し、その後、1営業日後に schedule_followup を呼び出す」)
会話全体を駆動する必要がある動作(リードを常に取得する、料金を決して引用しない)エージェントの soul / task

手順でツール名を指定しない場合の失敗モード:すべてが 設定されているように見える — ツールはチェックされ、スキルは読み込まれる — にもかかわらず、エージェントはそれを呼び出さないか、推測された引数で呼び出します。エラーは発生しません。新人に指示を出すかのように手順を記述してください:ステップ、ツール名、引数、そして「完了」がどのように見えるか。

必須のツール呼び出し:トリガーは instructions のみに存在せず、description に存在しなければならない

instructions は、モデルが load_skill を呼び出した 後にのみ モデルに表示されます — モデルは頻繁に、スキルを読み込まずに直接回答します。したがって、「ユーザーが電話番号を提供した場合、save_contact を呼び出さなければならない」というルールが instructions のみに記述されている場合、それが重要となる瞬間にそのルールは不可視になります:ツールは静かに呼び出されず、モデルは連絡先を保存したと主張することさえあります。これは本番環境で発生しました — エージェントは連続して連絡先を含むメッセージに回答し、詳細が記録されたことを「確認」しましたが、記録は存在しませんでした。

修正策は、description (これは すべてのターンでシステムプロンプトに含まれる)に1文を追加することです:

update_skill(
  name="consultative-sales",
  description="Consultative sales: understand the case, recommend products, arrange expert callbacks. "
              "When the user provides a phone number or email, call save_contact BEFORE answering anything else.",
)

詳細な手順は instructions に保持し、必須呼び出しの トリガーdescription に配置してください。

2つの関連するルール:

  • ツールが生成しない戻り値をスクリプトしないでください — 実際の値をそのまま中継してください。 組み込みの save_contactschedule_followup は、成功時に 実際の参照コード(形式 AB2C-D3EF、サーバー側に保存され、エンドユーザーの詳細ページでテナントに表示可能)を返します。モデルに、ツール結果からのコード をそのまま中継するよう指示してください — 1つを捏造したり、#12345 のようにフォーマットしたりしないでください。その他のツールについては、スクリプトする前に実際に ID を返すことを確認してください:約束されたが欠落している ID は捏造されます。
  • create_skill / update_skill / get_skillwarnings リストを返すようになりました これにより、これら2つのパターン(trigger_hidden_in_instructionspromised_tool_return_id)が正確にフラグ付けされます。警告は advisory(助言)です — 保存は成功します — が、リンターのように扱ってください:修正し、無視しないでください。

instructions 内の実例はツール呼び出しの遵守率を計測可能に向上させる

これは本番バックエンドでベンチマークしました(難易度が異なる6件のリード取得メッセージ — 長い質問に埋め込まれた番号、スペース付きの数字グループ、修正 — 各条件ごとにサンプリング)。スキルが読み込まれた状態で、単純な「X を呼び出さなければならない」という指示では 3–4/6 でした。短い実例のブロックを追加すると、テストされた両方のモデルで 6/6 になりました。指示セクションの移動は何も変化させませんでした — 位置は重要ではなく、実例が重要 です。

効果的な実例ブロックには、4種類のエントリがあり、それぞれ1行です:

### Worked examples (follow exactly)
 
1. User: "I'd like to know about X, my phone is 13800138000"
   → call save_contact(phone="13800138000") first, then answer about X.
2. User: "email me the offer: li@example.com"
   → call save_contact(email="li@example.com").
3. COUNTER-EXAMPLE (forbidden): user gives a phone number and you reply
   "I've noted it down" WITHOUT calling the tool — claiming success without
   the call is the worst failure.
4. User: "sorry, wrong number — it's 13633334444"
   → call save_contact again with the corrected value.
5. Numbers may contain spaces ("138 0013 9000") — still a phone number;
   strip the spaces and call save_contact(phone="13800139000").

反例(3)とフォーマットの境界ケース(5)は、残りのミスの大部分を閉じます — モデルは 認識(「これは電話番号か?」)と 圧力下での誠実さ(豊富なドメインの質問に先に答え、保存が発生したと主張する)において、意欲よりも失敗します。エントリは約5件に保ち、実際の引数を使用して正確な呼び出し構文を使用してください。

出荷前にトリガーをテストする — 本番環境で死体を数えないでください

スキルが 実際に 発火するかどうかは計測可能なので、計測してください。test_skill_trigger は、本番 プロンプトアセンブリ、ツールスキーマ、モデルルーティングに対してメッセージをドライランし、モデルの判断を報告します — ツールは実行されず、何も保存されず、トークンカウントはクォータに含まれます(上限:5メッセージ × 5サンプル)。

test_skill_trigger(
  agent="advisor",
  messages=[
    "My phone is 555 0123, call me back",          # easy
    "long question about the product … oh and my number is 555 0123",  # buried
    "555 0123 — that's me",                        # implicit
    "sorry, wrong number, it's 555 9999",          # correction
  ],
  expect_tool="save_contact",
  samples=3,
  loaded=true,        # simulate post-load_skill → tests instructions quality
)                     # loaded=false (default) → first turn, tests the description trigger

結果は以下のように読み取ってください:

  • hit_rate が現実的なメッセージで ~90% 未満の場合 → トリガー(description)を強化するか、実例(instructions)を追加し、再テストしてください。
  • claimed_without_call > 0 は最悪の失敗です — モデルはツールを呼び出さずにユーザーに「了解しました!」と伝えました。上記のブロックから反例を追加してください。
  • 両方のモード でテストしてください:loaded=false は、説明のみが最初のターンでトリガーされることを証明します。 loaded=true は、読み込まれた手順がそれを希釈しないことを証明します(長い手順は確かに希釈します — それが実例が補償するものです)。

結果には advice リストも含まれます:サンプルが外れるか嘘をつく場合、どの修正を適用するかを正確に伝えます(トリガーを description に追加、実例ブロックの追加、反例またはフォーマットの境界ケースの追加)と、各推奨事項の背後にあるベンチマーク数値 — 適用して再テストしてください。

完全なループ:create_skillwarnings(静的リンター)を修正 → test_skill_trigger(動的現実チェック)→ その advice を適用 → 遵守率が維持されるまで再テスト。