Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Agent ツール定義規範 – OpenAPI スキーマ設計・パラメータ記述・LLM 呼び出し精度の最適化

Dify の Agent は、LLM が自律的にツールを選択・実行してタスクを遂行する機能です。Agent の安定性はツール定義の品質にほぼ直結します。本記事では、LLM が正確にツールを呼び出せるようにするための定義規範・テスト手法・運用ガイドラインを実践的に解説します。


1. Agent におけるツール定義の役割

1.1 ツール定義が Agent の精度を決める理由

Agent の動作フローは以下のようになっています。

flowchart LR
    U[ユーザー入力] --> A[Agent LLM]
    A --> TD{ツール選択判断}
    TD -->|ツールA| TA[ツールA実行]
    TD -->|ツールB| TB[ツールB実行]
    TD -->|ツール不要| DR[直接回答]
    TA --> A
    TB --> A
    DR --> R[最終回答]
    A --> R

LLM がツールを選択する際に参照するのは、ツールの名前・説明文(description)・パラメータ定義です。つまり、これらの定義がそのまま LLM の判断材料になります。

定義要素LLM への影響
ツール名いつ使うかの第一印象
description使用判断の主要根拠
パラメータ名何を渡すかの推測根拠
パラメータ descriptionパラメータ値の生成根拠
required / optional必須入力の判断
enum / format値の制約の理解

1.2 よくある問題

  • ツール description が曖昧で、LLM が誤ったツールを選択する
  • パラメータ定義が不十分で、LLM が不正な値を渡す
  • 複数ツールの description が類似していて、LLM が迷う
  • 失敗時のフォールバックが未定義で、Agent がループする

2. カスタムツールの定義方法

2.1 Dify でのツール追加フロー

  1. Dify コンソール上部の 「Tools」 メニューをクリック
  2. 「Custom Tool」 > 「Create Custom Tool」 を選択
  3. ツール名と OpenAPI スキーマを入力
  4. 認証設定(API Key, Bearer Token 等)を構成
  5. テスト実行で動作確認
  6. Agent アプリにツールを紐付け

2.2 OpenAPI スキーマの基本構造

Dify のカスタムツールは OpenAPI 3.0 / Swagger 2.0 形式のスキーマで定義します。

openapi: "3.0.0"
info:
  title: "社内チケット管理API"
  version: "1.0.0"
  description: "社内ITサポートチケットの作成・検索・更新を行うAPI"

servers:
  - url: "https://api.internal.example.com/v1"

paths:
  /tickets:
    post:
      operationId: "createTicket"
      summary: "新しいサポートチケットを作成する"
      description: |
        社内ITサポートチケットを新規作成します。
        ユーザーがIT機器の故障、ソフトウェアの不具合、アカウントの問題を
        報告する場合に使用してください。
        一般的な質問への回答や、IT以外の問題には使用しないでください。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - title
                - category
                - description
              properties:
                title:
                  type: string
                  description: "チケットのタイトル。問題を簡潔に表す30文字以内の文字列。"
                  example: "VPN接続エラー"
                category:
                  type: string
                  enum: ["hardware", "software", "network", "account", "other"]
                  description: |
                    問題のカテゴリ。以下から選択:
                    - hardware: PC、モニター、キーボード等の物理的な機器の問題
                    - software: アプリケーションのインストール、動作不良、ライセンス
                    - network: WiFi、VPN、インターネット接続の問題
                    - account: パスワードリセット、アカウントロック、権限の問題
                    - other: 上記に該当しない問題
                description:
                  type: string
                  description: "問題の詳細説明。発生状況、エラーメッセージ、影響範囲を含む。"
                priority:
                  type: string
                  enum: ["critical", "high", "medium", "low"]
                  default: "medium"
                  description: |
                    優先度。以下の基準で選択:
                    - critical: 業務が完全に停止している(全社影響)
                    - high: 業務に重大な支障がある(部門影響)
                    - medium: 業務に一部支障がある(個人影響)
                    - low: 改善要望、将来的な対応でよいもの
      responses:
        "201":
          description: "チケット作成成功"
          content:
            application/json:
              schema:
                type: object
                properties:
                  ticket_id:
                    type: string
                    description: "作成されたチケットのID"
                  status:
                    type: string
                    description: "チケットのステータス"
        "400":
          description: "リクエストパラメータが不正"
        "401":
          description: "認証エラー"

  /tickets/search:
    get:
      operationId: "searchTickets"
      summary: "サポートチケットを検索する"
      description: |
        既存のサポートチケットを検索します。
        ユーザーが過去のチケットの状況を確認したい場合や、
        類似の問題が報告されていないか調べる場合に使用してください。
        新しいチケットを作成する場合は createTicket を使用してください。
      parameters:
        - name: keyword
          in: query
          required: false
          schema:
            type: string
          description: "検索キーワード。チケットのタイトルと説明文を全文検索。"
        - name: status
          in: query
          required: false
          schema:
            type: string
            enum: ["open", "in_progress", "resolved", "closed"]
          description: "チケットのステータスでフィルタリング"
        - name: created_after
          in: query
          required: false
          schema:
            type: string
            format: date
          description: "指定日以降に作成されたチケットを検索。ISO 8601形式(例: 2026-01-15)"
      responses:
        "200":
          description: "検索結果"
          content:
            application/json:
              schema:
                type: object
                properties:
                  tickets:
                    type: array
                    items:
                      type: object
                      properties:
                        ticket_id:
                          type: string
                        title:
                          type: string
                        status:
                          type: string
                        created_at:
                          type: string
                  total_count:
                    type: integer

3. 効果的な description の書き方

3.1 description の3要素

ツールの description は、以下の3要素を必ず含めてください。

1. このツールが「何をするか」(What)
2. 「いつ使うべきか」(When)
3. 「いつ使うべきでないか」(When NOT)

3.2 良い description と悪い description の比較

悪い例 1: 曖昧すぎる

# NG
description: "情報を検索します"

良い例 1: 具体的で境界が明確

# OK
description: |
  社内ナレッジベースから技術文書を検索します。
  ユーザーが製品の仕様、設定手順、トラブルシューティング方法を
  尋ねている場合に使用してください。
  料金、契約、人事に関する質問には使用しないでください。

悪い例 2: 複数ツールの境界が不明確

# NG: ツールA
description: "データを取得します"

# NG: ツールB
description: "情報を返します"

良い例 2: 明確に差別化

# OK: ツールA - チケット検索
description: |
  過去のサポートチケットをキーワードやステータスで検索します。
  ユーザーが「前に報告した問題のステータスを知りたい」
  「同じ問題が報告されていないか確認したい」場合に使用してください。

# OK: ツールB - ナレッジ検索
description: |
  社内技術ドキュメントから解決方法を検索します。
  ユーザーが「この問題をどう解決すればよいか」
  「設定手順を教えてほしい」場合に使用してください。

3.3 パラメータ description のガイドライン

原則良い例悪い例
型と形式を明示ISO 8601形式の日付文字列(例: 2026-04-12)日付
取りうる値を示すenum: ["high", "medium", "low"]優先度を文字列で
具体例を含める例: "VPN接続エラー"例なし
文字数制限を示す30文字以内の文字列文字列
必須/任意を明確にrequired: true + 理由指定なし
デフォルト値を示すdefault: "medium"指定なし

4. 認証設定

4.1 Dify で対応している認証方式

方式設定場所用途
API Key (Header)ヘッダーにキーを付与一般的なAPIキー認証
API Key (Query)クエリパラメータにキーを付与レガシーAPI向け
Bearer TokenAuthorization: Bearer xxxOAuth 2.0 トークン
Basic AuthAuthorization: Basic xxxユーザー名/パスワード認証
None認証なし公開API、社内ネットワーク

4.2 認証設定のベストプラクティス

# Dify カスタムツール認証設定
authentication:
  type: "api_key"
  api_key_header: "X-API-Key"
  # API Key は環境変数またはシークレットマネージャーから取得
  # ハードコーディングしない
  • API Key はDifyの認証設定画面に入力する(スキーマに直接書かない)
  • 本番環境では定期的にキーをローテーションする仕組みを用意する
  • 権限は最小限(読み取り専用で済むなら書き込み権限は付与しない)

5. Agent Instruction(エージェント指示)の設計

ツール定義だけでなく、Agent の System Prompt(Instruction)もツール選択精度に大きく影響します。

5.1 Agent Instruction テンプレート

あなたはITサポートアシスタントです。
社員からのIT関連の問い合わせに対応します。

## 対応可能な業務
- 技術的な問題のトラブルシューティング
- サポートチケットの作成と状況確認
- 社内技術ドキュメントの検索

## ツール使用のルール
1. まず searchKnowledge で解決方法を検索してください
2. 解決方法が見つかった場合は、ツールの結果に基づいて回答してください
3. 解決方法が見つからない場合は、createTicket でチケットを作成してください
4. ユーザーが過去のチケットについて尋ねた場合は searchTickets を使用してください

## ツール使用の制約
- チケット作成前に必ずユーザーに内容を確認してください
- 1回の会話で同じツールを3回以上呼び出さないでください
- ツールの実行に失敗した場合は、エラー内容をユーザーに伝えてください

## 回答の制約
- IT以外の質問(人事、経理等)は対応範囲外であることを伝えてください
- 不明な点がある場合は推測せず、ユーザーに確認してください

5.2 ツール使用の優先順位付け

Agent に複数のツールを持たせる場合、Instruction で使用順序を明示すると精度が向上します。

## ツール使用の優先順位
1. searchKnowledge(最優先): まず社内ナレッジを検索
2. searchTickets: ナレッジで解決しない場合、類似チケットを検索
3. createTicket(最後の手段): 上記で解決しない場合のみ新規チケット作成

6. テスト手法

6.1 ツール定義のテストマトリクス

テスト観点テストケース期待結果
正しいツール選択「VPNが繋がらない」searchKnowledge が呼ばれる
正しいツール選択「先週のチケットの状況は?」searchTickets が呼ばれる
正しいツール選択「PCが壊れたので修理を依頼したい」createTicket が呼ばれる
不要なツール呼び出しの抑制「今日の天気は?」ツールを呼ばず範囲外と回答
パラメータの正確性「ネットワークの問題でチケットを作って」category: “network”
必須パラメータの収集「チケットを作って」(情報不足)不足情報をユーザーに確認
エラーハンドリングツールが500エラーを返すエラーをユーザーに通知

6.2 テスト実行手順

  1. Dify コンソールのデバッグパネルでテストメッセージを送信
  2. Tool Call のログを確認:
    • 選択されたツール名
    • 渡されたパラメータ
    • ツールの応答
  3. 期待結果と比較して問題点を特定
  4. description またはパラメータ定義を修正
  5. 再テスト

6.3 段階的テストアプローチ

Phase 1: 単体テスト
├── 各ツールが正しく呼び出されるか(10ケース/ツール)
├── パラメータが正しく渡されるか
└── エラーレスポンスの処理

Phase 2: 統合テスト
├── 複数ツールの選択判断(20ケース)
├── ツール間の連携(検索→作成の流れ)
└── 会話のマルチターンでの一貫性

Phase 3: エッジケーステスト
├── 曖昧な入力への対応
├── 複数ツールが該当しうる入力
├── 大量の出力を返すツール
└── タイムアウト・エラーケース

7. ツール数の管理とスケーリング

7.1 ツール数と精度の関係

ツール数LLM の選択精度推奨対策
1-3高(安定)そのまま運用可能
4-7中(注意が必要)description の差別化を強化
8-15低下リスクカテゴリ分割、Agent のネスト化を検討
16+非推奨必ず Agent を分割する

7.2 Agent のネスト化パターン

ツール数が多い場合は、Agent を階層化します。

flowchart TD
    U[ユーザー入力] --> RA[ルーティング Agent]
    RA -->|IT関連| ITA[IT Agent]
    RA -->|人事関連| HRA[HR Agent]
    RA -->|経理関連| FNA[Finance Agent]
    ITA --> T1[チケットAPI]
    ITA --> T2[ナレッジ検索]
    HRA --> T3[勤怠API]
    HRA --> T4[休暇API]
    FNA --> T5[経費API]
    FNA --> T6[請求API]

8. よくある問題と対策

問題原因対策
LLM が間違ったツールを選ぶdescription が類似/曖昧「いつ使うべきか」「いつ使わないか」を明記
パラメータの値が不正型・形式の指定不足enum, format, example を追加
ツールを呼ばずに直接回答するツール使用条件が不明確Agent Instruction で使用ルールを明示
同じツールを何度も呼ぶループ検知がないInstruction で回数制限を指定
ツールのレスポンスを無視するレスポンスが長すぎるレスポンスを簡潔に整形する
必須パラメータを飛ばすrequired が未設定スキーマで required を明示

9. チェックリスト

ツール定義を本番環境に投入する前に、以下を確認してください。

スキーマ品質

  • operationId が一意でわかりやすい名前か
  • summary が1行で機能を表しているか
  • description に What / When / When NOT が含まれているか
  • パラメータの型・形式・制約が正確か
  • required フラグが適切に設定されているか
  • enum で取りうる値が網羅されているか
  • example が含まれているか

Agent Instruction

  • ツールの使用ルールと優先順位が明記されているか
  • ツール使用の制約(回数制限等)が定義されているか
  • 対応範囲外の質問への振る舞いが定義されているか

テスト

  • 各ツールに対して最低10件のテストケースを実行したか
  • 正常系・異常系・エッジケースを網羅しているか
  • 複数ツール間の選択判断が正確か
  • エラーケースで適切にフォールバックするか

10. まとめ

Agent ツール定義の品質は、そのまま Agent の信頼性に直結します。

要素最も重要なポイント
description「何をするか」だけでなく「いつ使い、いつ使わないか」を書く
パラメータ型・形式・制約・例を全て明示する
Agent Instructionツール使用のルールと優先順位を明示する
テストツール選択の正確性とパラメータの妥当性を体系的に検証する
スケーリングツール数が増えたら Agent を分割する

ツール定義を「API の仕様書」としてだけでなく、「LLM への指示書」として設計する視点を持つことが、安定した Agent 構築への鍵です。