🛠️ 第十二章:Custom Tools 専用武器の作成 (AIに手足を与える)

前章の実戦では、CrewAIを使って「研究者」と「ライター」を含む仮想チームを構築しました。 研究者には標準装備の武器であるSerperDevTool(Google検索ツール)を与え、自分でネット上の情報を検索できるよう��しました。

しかし、実際のビジネスシーンで最も価値のあるデータはGoogle上にはなく、会社の内部データベースにあるのです! もし上司がAIに「先月クレームが多かったキャンプ場ランキング分析」を作成するよう指示しても、AIがGoogle検索で見つけることはできません。 AIに「鍵」を与え、会社のSupabaseデータベースにアクセスしてクレーム記録を抽出する方法を教える必要があります。

このマスター級実戦講座では、Agentic AIの最も核心的な領域である**カスタムツール(Custom Tools)**の世界へご案内します。 普通のPython関数を、AIが理解でき「いつ使うべきかを自分で判断する」超兵器に変える方法を教えます!


🔧 実戦 1:誤解を解く、AIのToolとは何か?

多くのエンジニアは、Toolとは単にフロントエンドから呼び出すAPIを作ることだと思っています。全く違います。 CrewAI(およびLangChain)のエコシステムでは、Toolは2つの魂を持たなければなりません:

  1. 実行ロジック(Pythonコード):AIがこのツールを使うと決めた時に実際に実行されるコード。
  2. 使用説明書(DocstringとType Hint):これが最も重要!AIの脳に向けて書かれたテキストで、「このツールは何をするのか」「渡すパラメータはどんな形式か」を伝えます。

💡 Vibe Prompt 実戦 1:最も基本的な計算機ツール

大規模言語モデルは数学が苦手です(確率で文字を推測しているため)。345掛ける678と聞かれると、でたらめな数字を答えるかもしれません。 AIに絶対に間違えない計算機を装備させましょう。

[!IMPORTANT] 以下のPromptをAIにコピーして送信してください:

CrewAIシステムを開発中で、Agentが正確に計算できるカスタムツール(Custom Tool)が必要です。 @toolデコレータを使ってPython関数calculate_math(expression: str)を作成してください。 要件: 1. from langchain.tools import toolをインポート。 2. Pythonのeval()を使って渡された数式(expression)を計算。 3. このツールをいつ使うべきかAIに伝える非常に詳細なdocstringを必ず追加。 4. 式のフォーマットエラーでクラッシュしないようtry-exceptを追加。

🤖 AIの神級計算アドオン:

from langchain.tools import tool

# @toolデコレータが魔法の鍵で、この普通の関数をAIツールオブジェクトに変換します
@tool("数学計算マスターツール")
def calculate_math(expression: str) -> str:
    """
    これは強力な数学計算機です。
    大規模言語モデル(つまりあなた)は複雑な数学計算を間違えることがあります。
    タスクに精密な計算が必要な数学問題(例:加減乗除、パーセンテージ計算、合計計算)が含まれる場合、
    必ずこのツールを使用して正しい答えを得てください。自分で推測してはいけません。
    
    パラメータ'expression'は有効なPython数式文字列でなければなりません。
    入力例:"2500 * 0.15" または "(1200 + 800) / 4"
    """
    try:
        # evalを使って安全に数式文字列を計算
        # (実戦では絶対的安全のため、より厳密な数学解析ライブラリを使いますが、ここでは簡単なデモンストレーションとします)
        result = eval(expression)
        return f"式 '{expression}' の計算結果は:{result}"
    except Exception as e:
        return f"計算エラーが発生しました。式のフォーマットを確認してください。エラー詳細:{str(e)}"

🔍 深層解析: 気づきましたか?このコードで最も長い部分は"""..."""(Docstring)です。 これを書かないと、AIはこのツールをどう使っていいかわかりません。 しかし、「必ずこのツールを使って、自分で推測してはいけない」という警告を加えることで、AIはビジネスレポートで割引計算が必要な場面で、きちんと立ち止まり、calculate_math("3999 * 0.8")を呼び出し、3199.2を得た後、文章を続けるようになります。これがフールプルーフの極致です!


🗄️ 実戦 2:AIにSupabaseデータベースを検索させる

ここからビジネス実戦に入ります。特定のキャンプ場の「リアルタイム空き状況」を検索できるツールを作成します。

💡 Vibe Prompt 実戦 2:データベース検索ツールの作成

[!IMPORTANT] 以下のPromptをAIにコピーして送信してください:

CrewAIのカスタムツールcheck_camp_vacancy(camp_id: str)を作成してください。 要件: 1. supabase-pyを使ってSupabaseに接続(クライアント変数はsupabase_clientと仮定)。 2. "camps"テーブルからidがcamp_idの"vacancy_count"カラムを検索。 3. 見つからない場合は"該当するキャンプ場が見つかりません"と返す。 4. camp_idがUUID形式であることをAIに伝える完全なdocstringを記述。

🤖 AIのデータベース直結チャネル:

import os
from langchain.tools import tool
from supabase import create_client

# 接続初期化
supabase_client = create_client(os.getenv("SUPABASE_URL"), os.getenv("SUPABASE_KEY"))

@tool("キャンプ場空き状況検索システム")
def check_camp_vacancy(camp_id: str) -> str:
    """
    これはキャンプ場のリアルタイム空き状況を検索する内部データベースツールです。
    顧客やタスクでキャンプ場の「空きがあるか」「いくつ空きがあるか」を確認する必要がある場合、このツールを呼び出してください。
    
    パラメータ'camp_id'はキャンプ場の一意の識別子でなければなりません(通常は英数字の長い文字列、例:'a1b2-c3d4...')。
    キャンプ場の日本語名を渡さないでください!日本語名しかわからない場合は、まず他の検索ツールでIDを調べてください。
    """
    print(f"🕵️‍♂️ [システムログ] AIがデータベースを検索中、対象キャンプ場ID: {camp_id}")
    try:
        response = supabase_client.table("camps").select("name, vacancy_count").eq("id", camp_id).execute()
        
        # データが取得できたか確認
        if len(response.data) > 0:
            camp_info = response.data[0]
            return f"キャンプ場『{camp_info['name']}』の現在の空き状況:{camp_info['vacancy_count']} サイト。"
        else:
            return f"エラー:ID {camp_id} のキャンプ場はデータベースに見つかりませんでした。"
            
    except Exception as e:
        return f"データベース接続で異常が発生しました:{str(e)}"

📧 実戦 3:AIにEmail送信権限を与える(Action Tools)

これまでのツールは「読み取り(Read)」で比較的安全です。 しかし、AI従業員が「自動マーケティングの達人」で、プロモーション記事を書いた後、直接顧客に「自分でメールを送信」できるようにしたい場合はどうでしょうか? これは**Action(アクション実行)**ツールと呼ばれ、非常に強力ですが、極めて危険でもあります!

💡 Vibe Prompt 実戦 3:Email送信ボタンの作成

[!IMPORTANT] 以下のPromptをAIにコピーして送信してください:

カスタムツールsend_marketing_email(recipient_email: str, subject: str, content: str)が必要です。 このツールはAIが自分でマーケティングメールを送信できるようにします。 概念を示すた��、実際のSMTP送信コードは不要で、print()で送信過程を模倣してください。 重要なのは:docstringで、AIに送信前に攻撃的な内容がないこと、件名が魅力的であることを厳重に警告することです。 完全なコードを提供してください。

🤖 AIの全自動メール送信機:

from langchain.tools import tool

@tool("自動Email送信システム")
def send_marketing_email(recipient_email: str, subject: str, content: str) -> str:
    """
    これは実際のEmailを外部に送信する危険なツールです!一度呼び出されると、メールは即座に送信され、取り消せません。
    
    マーケティング文案の作成が完了し、「顧客に送信」するよう指示された場合、このツールを使用してください。
    パラメータ説明:
    - recipient_email: 対象顧客のEmailアドレス(正しいメール形式でなければなりません)。
    - subject: メール件名。誤字がなく、非常に魅力的であることを確認してください。
    - content: メール本文(プレーンテキストまたはHTML形式対応)。
    
    【警告】:送信前にcontentを徹底的に確認し、虚偽のプロモーションコードや不正確な価格約束を含めないでください!
    """
    
    # 実際の実装ではsmtplibやSendGridなどのサードパーティサービスを使用
    print("\n" + "="*50)
    print("🚨 [アクション警告] AIが現実世界の操作をトリガーしました!")
    print(f"📧 送信先: {recipient_email}")
    print(f"📌 件名: {subject}")
    print(f"📝 本文プレビュー: {content[:50]}...")
    print("="*50 + "\n")
    
    return f"システム報告:メール '{subject}' は {recipient_email} に正常に送信されました。"

🎭 実戦 4:複数ツールの組み合わせ技でAIを超人にする

現在、3つのツールがあります:計算機、データベース検索、メール送信機。 これらを1つのAgentに装備させ、驚くべき化学反応を見てみましょう。

💡 Vibe Prompt 実戦 4:万能傭兵を武装させ複雑なタスクを実行

[!IMPORTANT] 以下のPromptをAIにコピーして送信してください:

先程の3つのツール(calculate_math, check_camp_vacancy, send_marketing_email)を統合してください。 1. スーパーAgent(Sales & Marketing Exec)を作成し、これら3つのツールをtools=[]に追加。 2. 非常に複雑なTaskを作成。シナリオは以下の通り: "上司がID 'camp-123'のキャンプ場をVIP顧客vip@example.comにプロモーションするよう指示。" "まずこのキャンプ場の空き状況を確認する必要がある。" "空きがあれば、貸切(1サイト1200円と仮定)で20%割引の総額を計算する。" "最後に、この情報を非常に熱意あるEmailにまとめ、ツールを使って送信する。" これら全てを統合したCrewAI実行スクリプトを提供してください。

🤖 AIの究極自動化デモンストレーション:

from crewai import Agent, Task, Crew, Process

# 1. 3つの神器を装備したスーパーセールスマンを作成
super_sales = Agent(
    role='トップセールス&マーケティングディレクター',
    goal='データと精密計算を活用し、VIP顧客が拒否できないプロモーションメールを送信する。',
    backstory='あなたは冷静で論理的、しかし文章は非常に説得力のあるトップセールスです。決して間違えず、必ずデータベースで確認します。',
    verbose=True,
    # 🔥 完全武装!
    tools=[check_camp_vacancy, calculate_math, send_marketing_email]
)

# 2. マルチステップ推論が必要な超複雑タスクを割り当て
vip_sales_task = Task(
    description=(
        "これは緊急のハイエンドセールスタスクです!\n"
        "1. まずキャンプ場ID 'camp-123'の空き状況を確認してください。\n"
        "2. 1サイトあたり1200円と仮定します。残りのサイトを『全サイト貸切』し、20%割引(0.8)を適用した総額を計算してください。\n"
        "3. 『残りサイト数』と『割引後の総額』を、熱意とVIP待遇感あふれる招待状にまとめてください。\n"
        "4. 送信先は 'vip@example.com'です。\n"
        "5. 最後に、送信アクションを実行してください。"
    ),
    expected_output="送信完了後、送信したメールの件名と総額を報告してください。",
    agent=super_sales
)

# 3. 本部を起動!
sales_crew = Crew(
    agents=[super_sales],
    tasks=[vip_sales_task],
    process=Process.sequential,
    verbose=True
)

print("🚀 スーパーセールスマンを起動、奇跡を目撃しましょう...")
# 注意:このコードを正常に実行するには、Supabaseツールの応答をモック(模擬)する必要があります。そうしないとcamp-123が見つからずエラーになります
sales_crew.kickoff()

🔍 深層解析(ターミナルで起こること): 実行すると、AIの脳(super_sales)の思考プロセス(Thought Process)が見られます。この対話は百万ドルの価値があります:

  1. 思考: camp-123の空き状況をまず知る必要がある。 アクション: check_camp_vacancy('camp-123')を呼び出し 観察: キャンプ場『星空部落』の現在の空き状況:15サイト。
  2. 思考: 了解、15サイト空いている。1サイト1200円、全サイト貸切で20%割引。総額を計算しなければ。 アクション: calculate_math('15 * 1200 * 0.8')を呼び出し 観察: 計算結果は:14400.0
  3. 思考: データが揃った!メールを作成し、送信する。 アクション: send_marketing_email('vip@example.com', '【VIP限定タイムセール】星空部落 15サイト完全貸切特典', '親愛なるVIP様... 総額14,400円にて...')を呼び出し 観察: システム報告:メールは正常に送信されました。

これがAgentic Workflowの極致です! もはや単なるQ&Aではなく、「推論」「計画」「ツール呼び出しによるデータ修正」「最終アクション実行」を学んだのです。コンピュータ内に完全自動化されたマーケティング部門を構築したようなものです!


✅ 本章のまとめと究極アーキテクチャの秘訣

この6000字に及ぶカスタムツール実戦で、大規模言語モデルの致命的な「知識の盲点」と「数学音痴」の限界を打ち破りました。

スーパーブレイン構築の鍵を振り返ります:

  1. **@toolデコ

完全なチュートリアルをロック解除

このチャプターは有料コンテンツです。プロジェクトに参加して、10以上の神レベルのPromptや実際のソースコード例を含む、5000字以上の深い分析をロック解除してください!