
# カスタム関数

カスタム関数を使用すると、AIボットがライブ会話中に他のシステムと接続できるようになります。「確認して折り返します」と言う代わりに、ボットが注文状況を検索したり、在庫を確認したり、CRM（HubSpotやSalesforceなど、リードや顧客を追跡するために使用する顧客関係管理システム）にレコードを作成したりできます。これらすべてを、顧客を待たせることなくリアルタイムで行うことができます。


---

## カスタム関数とWebhookの違い

これは最もよくある混乱のポイントですので、何かを構築する前に明確にしておく価値があります。

| | Webhook | カスタム関数 |
|---|----------|------------------|
| **方向性** | 一方向（送信して終了） | 双方向（呼び出して待機） |
| **ボットの動作** | 何かが発生したときに通知を送信し、そのまま処理を続行します。 | 外部を呼び出し、**一時停止して応答を待ち**、返ってきた内容を使用して会話を続けます。 |
| **会話への可視性** | 下流の結果はボットからは見えず、何が起こったのかを認識できません。 | 応答が直接AIに戻されるため、ボットはその内容を引用したり、推論したりして、顧客に返答できます。 |
| **最適な用途** | イベントのログ記録、CRMへのデータ同期、外部自動化（Zapier、Make、n8n）のトリガー。 | ボットが返答する前に**回答**が必要なあらゆる処理（ライブ検索、リアルタイム価格照会、オンザフライのコンテンツ生成）。 |

**どちらを選ぶべきか:** 何かが発生したことを別のシステムに*通知*するだけでよい場合は、Webhook（別のシステムに送信される一方向の自動メッセージ。**設定 → インテグレーション → Webhook**を参照）を使用してください。ボットが会話を続ける前に別のシステムから何かを*学習*する必要がある場合は、カスタム関数を使用します。

---

## カスタム関数で実現できることの例

応答が会話にフィードバックされるため、カスタム関数はWebhookでは不可能なことを実現します。

- **ShopifyやWooCommerceのライブ在庫検索** — 顧客に見積もりを出す前に、ボットがリアルタイムで在庫を確認し、「確認して折り返します」と言う代わりに「はい、Mサイズが12個あります」と回答します。
- **Googleスプレッドシートからの動的価格設定** — 営業チームがシートの価格を更新すると、ボットは会話の途中で最新の行を読み取り、AI設定を誰も触ることなく現在の価格を提示します。
- **音声AIコールバックエージェント** — ボットがリードを適格と判断すると、音声エージェント（例：ElevenLabsを利用した発信者）を起動して数分以内にリードに電話をかけさせ、顧客に「承知いたしました。5分以内に電話があります」と伝えます。
- **カスタム見積もりPDFの生成とチャット中のメール送信** — ボットが要件を収集し、見積もり作成ツールを呼び出してPDFのURLを取得し、顧客に「見積もりをメールで送信しました。受信トレイを確認してください」と伝えます。

---

## カスタム関数で何ができるか？

カスタム関数は、ボットに単なる会話以上のスーパーパワーを与えるものだと考えてください。実際の例をいくつか挙げます。

- **注文追跡** - 顧客が「注文はどこですか？」と尋ねると、ボットがeコマースシステムを確認し、配送状況と追跡リンクを返信します。
- **在庫確認** - 「サイズ10はありますか？」という質問に対し、ボットが在庫システムを確認してリアルタイムで回答します。
- **CRMの更新** - ボットがリードを適格と判断すると、HubSpot、Salesforce、その他のCRMのレコードを自動的に作成または更新します。
- **見積もり生成** - ボットが顧客の要件を収集し、価格設定システムからパーソナライズされた見積もりを生成します。
- **予約** - ボットが外部の予約システムにアポイントメントを作成します。
- **割引の検証** - 「このクーポンコードは有効ですか？」という質問に対し、ボットが確認して回答します。
- **アカウント検索** - リピーターの顧客を自動的に認識し、アカウント詳細を呼び出します。

**顧客は舞台裏で何が起こっているのかを知ることはありません。** 彼らは単に、最新の正確な情報で質問に答えてくれるボットを体験するだけです。

---

## カスタム関数の仕組み（簡易版）

会話中にカスタム関数がトリガーされると、以下のような処理が行われます。

1. **顧客が何かを尋ねる**（例：「注文はどこですか？」など、リアルタイムのデータが必要な場合）
2. **ボットが認識する**（回答するためにカスタム関数を使用する必要があることを認識します）
3. **ボットが情報を収集する**（不足している情報を顧客から収集します。例：「注文番号は何ですか？」）
4. **プラットフォームがリクエストを送信する**（関連する詳細情報とともに、お客様のシステム（Webサイト、CRM、その他のツール）へリクエストを送信します）
5. **システムが応答する**（データ（注文状況、追跡番号、配送日など）を返します）
6. **ボットが応答を読み取る**（自然な返信を作成します。「ご注文 ORD-4582 は発送済みで、金曜日までに到着予定です！」）

### カスタム関数呼び出しのコスト

各カスタム関数呼び出しは、エージェントのAI品質ティアに基づいて課金されます：

| AI品質ティア | カスタム関数呼び出しあたりのクレジット | 独自のAnthropicキー（BYOK）を接続している場合 |
|---|---|---|
| Pro | 1クレジット | 0クレジット — 独自のキーで実行 |
| Economy (非推奨) | 0.5クレジット | 0クレジット — 独自のキーで実行 |
| Max | 0.25クレジット | 0.25クレジット — 独自のキーを接続していても課金されます（Maxは当社のモデルで実行されるため） |
| Mini | 0.15クレジット | 0.15クレジット — 独自のキーを接続していても課金されます（Miniは当社のモデルで実行されるため） |

---

## カスタム関数の設定（ステップバイステップ）

1. メインサイドバーの **AI Studio** で、**Custom Functions** をクリックします。


2. 右上の緑色の **+ Add Function**（または **New function**）ボタンをクリックします。


カスタム関数リストには、以下の列を持つテーブルが表示されます。

| 列 | 表示内容 |
|--------|--------------|
| **Name** | 関数名（例: `check_order_status`） |
| **Description** | 関数が何を行うかの短い要約（テーブル内では50文字に切り詰められます） |
| **Method** | 使用されるHTTPメソッド。色付きのバッジで表示されます：GET（青）、POST（緑）、PUT（オレンジ）、DELETE（赤） |
| **Created** | 関数が作成された日付 |

これにより、関数を一目で確認し、必要なものを簡単に見つけることができます。

### ステップ 1: 名前と説明を入力する


| フィールド | 入力内容 | 例 |
|-------|--------------|---------|
| **Name** | 英数字とアンダースコアを使用した短い名前 | `check_order_status` |
| **Description** | この関数が何を行うかを説明（AIが使用タイミングを判断するために読み取ります） | "注文番号を使用して顧客の注文状況を検索する" |
| **Purpose (AI Action)** | AIに対し、いつどのようにこの関数を使用するかを正確に指示 | "顧客が注文状況、配送、配達について尋ねたときに使用してください。最初に注文番号を尋ねてください。" |

**ヒント:** 説明と目的は非常に具体的に記述してください。関数を使用すべきタイミングを明確にすればするほど、ボットは適切なタイミングでより確実にそれを使用できるようになります。

### ステップ 2: 接続を設定する

リクエストの送信先をアプリに指定する必要があります。

| フィールド | 入力内容 | 例 |
|-------|--------------|---------|
| **URL** | システムのエンドポイントのWebアドレス（リクエストを受信してデータを返信するシステム上の特定のアドレス） | `https://api.yourstore.com/v1/orders/status` |
| **メソッド** | 送信するリクエストのタイプ | 以下のオプションを参照 |

**どのメソッドを選択すべきか:**

| メソッド | 使用タイミング |
|--------|---------------|
| **GET** | 情報を検索する場合（注文状況、在庫、アカウント詳細など） |
| **POST** | 新しいレコードを作成する場合（サポートチケット、リード、予約など）や複雑な検索を行う場合 |
| **PUT** | 既存のレコードを完全に更新する場合 |
| **PATCH** | 既存のレコードの一部を更新する場合 |
| **DELETE** | レコードを削除する場合 |

どちらを使用すべきか不明な場合は、開発者または接続先システムのドキュメントを確認してください。**GET**（検索用）と**POST**（レコード作成用）が最も一般的です。

### ステップ 3: 認証ヘッダーを追加する

ほとんどのシステムでは、リクエストを受け入れるために認証が必要です。必要なヘッダーを追加してください：

| ヘッダー | 値の例 |
|--------|--------------|
| `Authorization` | `Bearer your-api-key-here` |
| `Content-Type` | `application/json` |

**セキュリティのヒント:** 権限を制限した専用のAPIキーを使用してください。管理者レベルの認証情報は使用しないでください。

**APIキーの場所:** 接続先システム（CRM、eコマースプラットフォーム、予約ツールなど）の設定または開発者向けセクションを確認してください。

### ステップ 4: 入力を定義する（ボットが送信する内容）

入力パラメーターは、ボットが会話から収集し、システムに送信する情報です。

各パラメーターについて、以下を指定します：

| プロパティ | 意味 |
|----------|--------------|
| **名前** | パラメーター名（システムが期待するものと一致させる必要があります） |
| **タイプ** | データの種類（テキスト、数値、真偽値など） |
| **説明** | この情報が何であるか、会話のどこにあるかをAIに伝えます |
| **必須** | 「はい」に設定すると、ボットは処理を進める前に顧客にこの情報を尋ねます |

**利用可能なパラメータータイプ：**

| 型 | 意味 |
|------|--------------|
| **string** | テキスト（名前、注文番号、住所など） |
| **number** | 数値（数量、価格など） |
| **boolean** | 真または偽（はい/いいえの値） |
| **array** | アイテムのリスト。実際のJSONリストとして送信されます。**テストの実行**では、`[8624]`、`["a", "b"]`、または単なるカンマ区切り（`8624, 8625`）として入力でき、自動的に変換されます。APIがリストの内容（数値のみなど）に対して厳格な場合は、型の横にあるオプションの**アイテム型**を設定すると、リスト内のすべての値がその型に変換されます。 |
| **query_param** | リクエストボディではなく、URLパラメータとして送信されるテキスト。APIがURL内のデータ（例: `?order_id=123`）を期待する場合に使用します。 |

各パラメータには、オプションの **Request body path**（リクエストボディパス）フィールドもあります。通常、パラメータはリクエストボディのトップレベルフィールドとして（または `query_param` 型の場合はクエリ文字列の値として）送信されます。エンドポイントがネストされた形式（例: `{"order": {"id": "ORD-123"}}`）を期待している場合は、パスを `order.id` に設定すると、プラットフォームが自動的にその場所に値をネストします。


**例：注文状況の検索の場合、以下のように定義します：**

- **order_number** (string, 必須): 「顧客の注文番号。通常はORD-の後に数字が続きます。顧客が言及していない場合は、これを尋ねてください。」
- **email** (string, 任意): 「追加確認のための顧客のメールアドレス。注文番号だけでは一致が見つからない場合にのみ必要です。」

### システムが自動的に受信するもの

定義した入力パラメータに加え、プラットフォームはすべてのリクエストにシステムデータを自動的に含めます。エンドポイントは、このデータを `system` フィールドで受信します。

| システムフィールド | 内容 |
|-------------|----------------|
| `system.contactId` | 会話内の連絡先のプラットフォームID |
| `system.campaignId` | 会話が属するキャンペーンID |
| `system.userId` | ユーザーID |
| `system.channel` | メッセージングチャネル（例: `"whatsapp"`, `"instagram"`） |
| `system.contact` | 完全な連絡先レコード（名前、電話番号、メールアドレス、タグなど） |
| `system.campaign` | キャンペーン設定 |
| `system.test` | これが「試用（Try Out）」テストの場合は `true`、ライブ会話の場合は `false` |

これは、システムが連絡先を識別する必要がある場合や、どのキャンペーンが関数をトリガーしたかを確認する場合、あるいはテスト中に異なる動作をさせる必要がある場合に役立ちます。

> **システムデータが不要な場合**：関数ビルダーで **システムデータをスキップ (Skip System Data)** トグルをオンにしてください。これにより、ボットは定義した入力パラメータのみを送信し、連絡先データやキャンペーンデータは送信されません。エンドポイントが予期しないフィールドを拒否する場合や、単にペイロードを軽量化したい場合に使用してください。

### ステップ 5: テストを実行し、ボットにレスポンスを読み取らせる

通常、レスポンスフィールドをマッピングする必要はまったくありません。エンドポイントが応答すると、ボットはJSONレスポンス全体を読み取り、関数の **Description**（説明）と **Purpose (AI Action)**（目的（AIアクション））、および各パラメータ自身の説明を使用して、何が重要かを判断し、自然な形で提示します。関数自体の明確な説明（「配送情報や追跡情報を含む顧客注文の現在のステータスを取得します」など）は、フィールドごとのマッピングよりもはるかに効果的です。

エンドポイントが大きなレスポンスを返し、ボットに特定のいくつかの値のみを認識させたい場合は、**Response mapping**（レスポンスマッピング）セクション（デフォルトでは折りたたまれており、Testのすぐ上にあります）を開いてください。各行でレスポンスから1つのトップレベルフィールドを選択します。**Response field** はAPIのJSON応答におけるフィールド名で、**Output field** はボットがそれを受け取る際の名称です。少なくとも1行を入力すると、ボットはレスポンスボディ全体ではなく、マッピングされた値のみを受け取ります。デフォルトの全レスポンスを受け取る動作を維持するには、このセクションを空のままにしてください。


保存する前に、ビルダー下部にある **Test** セクションを使用して、設定通りにリクエストを送信し、アプリを離れることなく実際のレスポンスを確認してください。


ここに表示されているレスポンスは、エンドポイントからの生の応答です。上記で**レスポンスマッピング**を設定している場合、実際のチャット内のボットはマッピングされたフィールドのみを受け取ります。テストでは常に完全な生のレスポンスが表示されるため、マッピング可能な項目を確認できます。もし何かがおかしい（予期しないフィールド名、余分なネストなど）場合は、エンドポイント側で修正するか、マッピングを調整してください。

---

## エージェントへの関数の割り当て

カスタム関数を作成した後、各エージェントに使用させる関数を指定する必要があります。

1. **AI Studio → AI Agents** から [Agent](../ai-agents/ai-agents.md) を開きます。
2. **AI Abilities** タブに移動します。（個別のエージェントではなく、キャンペーン自体にAI設定を保持している場合は、そのキャンペーンの **AI Abilities** ステップに同じリストが表示されます。）
3. 作成したすべてのカスタム関数のリストが表示されます。このエージェントのボットが呼び出せるようにしたい各関数をオンに切り替えます。
4. 下部にある **Save changes** をクリックします。選択内容は保存後にのみ適用されます。


割り当てられた関数のみが、そのエージェントのボットで使用可能です。これにより、ボットが関連性のない関数を誤って使用することを防ぎます。

---

## カスタム関数のテスト

本番環境で公開する前に、十分にテストを行ってください。

1. **組み込みテストの実行** - 関数ビルダー内の **Test** セクション（上記参照）を使用して、アプリを離れることなく簡単に確認します。現実的な値を入力し、「Run test」をクリックしてください。
2. **システムの直接テスト** - 以下のチェックリストを完全に網羅するには、Postmanのような専用ツールを使用して、「Run test」よりも詳細な調査を行います。
3. **Try Outでのテスト** - 顧客が関数をトリガーするような質問をした場合を想定した会話をシミュレーションします。
4. **レスポンスの確認** - ボットがデータを正しく読み取り、提示しているかを確認します。
5. **エラーシナリオのテスト** - 顧客が無効な注文番号を入力した場合はどうなるか？システムが一時的にダウンしている場合はどうなるか？

### テスト結果が 401 または 403 の場合

401 または 403 は、エンドポイントがリクエストを受信したものの、それを拒否したことを意味します。特徴的なのは、**自身のログに何も表示されない**ことです。ほとんどのツールは、ワークフローを開始する前に未承認の呼び出しを拒否するため、こちら側には何も表示されず、リクエストが一度も届かなかったように見えます。

これはほぼ間違いなく認証の不一致です。エンドポイントが要求する認証情報と、関数が送信している認証情報が異なっています。[ステップ 3](#step-3-add-authentication-headers) で追加したヘッダーが、システムが期待するものと完全に一致しているか確認してください。

**Basic Auth** で保護されたWebhook（n8n、Make、およびほとんどのセルフホストツールでは、Webhook自体のチェックボックスでこれを有効にできます）に対して、関数が `X-My-Secret` のようなカスタムシークレットヘッダーを送信している場合が最も一般的です。Basic Auth は `Authorization` ヘッダーのみを受け入れるため、カスタムヘッダーは無視され、呼び出しは拒否されます。以下の2つの選択肢があります。

- Webhookの **Basic Auth をオフ**にし、代わりにワークフロー内でカスタムヘッダーをチェックします。
- **Basic Auth をオンのまま**にし、関数に `Authorization` ヘッダーを追加します。その値は `Basic` という単語の後に base64 エンコードされた `username:password` を続けたものにします。

どちらの方法でも機能しますが、両側で設定が一致していることを確認してください。

### テスト結果が 404 の場合

エンドポイントのURLが間違っているか、ワークフローが公開されていません。特に n8n では、すべてのWebhookに個別の **Test** URL と **Production** URL があり、Test URL はエディタを開いている間のみリッスンします。Production URL をコピーし、ワークフローがアクティブであることを確認してください。

### 「試用」および「チャット」での失敗の確認

AIが会話中にカスタム関数を呼び出し、その呼び出しが失敗した場合（認証情報の誤り、エンドポイントのダウン、タイムアウトなど）、その状況が会話に表示されるようになりました。エージェントの**「試用」**タブと**「チャット」**での実際の会話の両方のスレッド内に、赤色の**「(関数名) failed」**というマーカーが表示されます。マーカーをクリックすると詳細が展開され、エンドポイントが返したステータスコードとレスポンスボディを確認できます。これらは通常、修正すべき箇所を特定するのに十分な情報です（「unauthorized」メッセージを含む `401` は認証ヘッダーの問題を、タイムアウトはエンドポイントの処理に30秒以上かかったことを示します）。

成功した呼び出しにもマーカーが表示されます。クリックすると、エンドポイントが実際に何を返したかを確認できます。これは統合をエンドツーエンドでデバッグする最も迅速な方法です。「試用」でテスト会話を行い、関数マーカーをクリックするだけで、ページを離れることなく実際の要求結果を確認できます。

---

## 完全な例：注文ステータスの照会

テンプレートとして使用できる、完全に設定された例を以下に示します。

**基本情報:**
- **名前:** `check_order_status`
- **説明:** "配送情報や追跡情報を含む、顧客の注文の現在のステータスを取得します"
- **AIアクション:** "顧客が注文状況、荷物の場所、到着予定日について尋ねたときにこれを呼び出します。必ず最初に注文番号を尋ねてください。"

**接続:**
- **URL:** `https://api.mystore.com/orders/lookup`
- **メソッド:** POST

**ヘッダー:**
- `Authorization`: `Bearer sk_live_abc123`
- `Content-Type`: `application/json`

**入力パラメーター:**
- `order_number` (text, 必須): "顧客から提供された注文番号"
- `customer_email` (text, 任意): "追加確認のための顧客のメールアドレス"

**レスポンスのマッピングは不要です** — 上記で明確な説明とAIアクションが設定されていれば、ボットはエンドポイントが返すJSON（ステータス、追跡番号、配送日、商品など）を読み取り、それについてどのように話すべきかを判断します。

**会話の例:**

> **顧客:** ねえ、私の注文はどこにあるの？
>
> **ボット:** こんにちは！注文状況をお調べしますね。注文番号を教えていただけますか？
>
> **顧客:** ORD-78234 です
>
> **ボット:** お調べします...
>
> ご注文 ORD-78234 は発送済みで、現在配送中です！到着予定日は3月10日です。こちらのリンクから荷物を追跡できます: https://tracking.example.com/1Z999AA1
>
> 他にお手伝いできることはありますか？

---

## 完全な例：Shopify注文ステータス

ストアがShopifyで運営されている場合、ルックアップエンドポイントを構築するために開発者は不要です。Shopifyのシステム自体が注文に関する質問に直接回答できます。（Shopifyストアの商品や在庫に関する質問の場合、カスタム関数は全く必要ありません。ストアの組み込みサーバーを接続してください。詳細は[Shopifyストアを接続する](mcp-servers.md#ready-made-example-connect-a-shopify-store)を参照してください。）

**まず、Shopifyでアクセストークンを作成します。** Shopifyは2026年中にこの仕様を変更しました。アプリはShopify管理画面内で作成できなくなり、新しいアプリ作成画面では、すぐに使えるトークンの代わりに**クライアントID**と**クライアントシークレット**が発行されるようになりました。以下の手順で、それらを永続的なトークンに変換します。ストアごとに1回、約10分かかります。（ストアですでに従来の方法で作成された古いアプリがある場合、既存のトークンはそのまま機能し続けるため、以下のカスタム関数の手順に直接進んでください。）

1. Shopify開発者ダッシュボード（[dev.shopify.com](https://dev.shopify.com)）にアクセスし、組織を開いて **Apps → Create app** をクリックします。`Order lookup` のような名前を付けます。
2. アプリに **read_orders** 権限を付与し、バージョンをリリースして、ストアにアプリをインストールします。
3. アプリの **Settings** を開き、ストア独自のWebアドレス（例：`https://www.yourstore.com/`）を許可されたリダイレクトURLに追加して保存します。
4. 同じく **Settings** で、**Client ID** と **Client secret** をコピーします。
5. そのストアのShopify管理画面にログインしているブラウザで、以下のURLを開きます。その際、ストア名、クライアントID、リダイレクトアドレスを自分のものに置き換えてください：
   `https://YOUR-STORE.myshopify.com/admin/oauth/authorize?client_id=YOUR-CLIENT-ID&scope=read_orders&redirect_uri=https://www.yourstore.com/&state=12345`
   表示された画面を承認します。ブラウザがリダイレクトアドレスに遷移し、アドレスバーに `code=` とそれに続く長い値が表示されます。その値をコピーしてください。これは数分間しか有効ではないため、すぐに次のステップに進んでください。
6. そのコードをトークンと交換します。これは <span data-t="appName">Your AI Connector</span> 内で行うことができます。カスタム関数ビルダーで、**Method** を POST に、**URL** を `https://YOUR-STORE.myshopify.com/admin/oauth/access_token` に設定し、`client_id`、`client_secret`、`code` という名前の3つのテキスト入力パラメータを追加します。次に「テスト」をクリックし、3つの値を入力して実行します。レスポンスに `access_token` が含まれます。これが永続的なトークンです。安全な場所にコピーしてから、ビルダーをクリアし、以下の手順で実際の関数をセットアップしてください。

**次に、カスタム関数を設定します：**

**基本情報：**
- **名前：** `check_shopify_order`
- **説明：** "ストアのShopifyシステムで注文を検索し、ステータス、追跡情報、商品情報を返します"
- **AIアクション：** "顧客が注文ステータスや配送について尋ねたときにこれを呼び出します。必ず最初に注文番号を尋ねてください。"

**接続：**
- **URL：** `https://YOUR-STORE.myshopify.com/admin/api/2026-01/orders.json?status=any` — `YOUR-STORE`をストアの`.myshopify.com`名に置き換えてください（このアドレスはストアのカスタムドメインではなく、技術的なShopifyドメインを使用します）
- **メソッド：** GET

**ヘッダー：**
- `X-Shopify-Access-Token`: `shpat_...` （上記で取得したトークン）

**入力パラメーター：**
- `name` (query_param, 必須): "注文確認メールに記載されている通りの注文番号（#記号を含む、例：#1001）。顧客が言及していない場合は尋ねてください。"

**レスポンスのマッピングは不要です** — ボットが返された注文情報（支払いステータス、配送ステータス、追跡情報、商品）を読み取り、自然に回答します。

**知っておくべきこと：** この方法で作成されたトークンは、**過去60日間**の注文を参照できます。日常的なサポートの質問には十分ですが、全注文履歴ではありません。

---

## 完全な例：予約の作成

**基本情報:**
- **名前:** `create_booking`
- **説明:** "予約システムに新しい予約を作成します"
- **AIアクション:** "日付、時間、連絡先を顧客と確認した後に使用してください。顧客が予約を明示的に希望するまで呼び出さないでください。"

**接続:**
- **URL:** `https://booking.mycompany.com/api/appointments`
- **メソッド:** POST

**入力パラメーター:**
- `date` (text, 必須): "YYYY-MM-DD形式の予約日"
- `time` (text, 必須): "HH:MM形式の予約時間"
- `name` (text, 必須): "顧客の氏名"
- `phone` (text, 必須): "顧客の電話番号"
- `service_type` (text, 必須): "予約するサービスの種類"

---

## 完全な例: ニュースレター購読者をCRMに追加する

非常によくあるパターンとして、ボットが回答を終えた後にニュースレターを提案し、連絡先がメールアドレスで返信し、そのアドレスを即座にメールツールへ登録するというものがあります。ほとんどのCRM（FluentCRM、ActiveCampaign、MailerLite、Brevoなど）は、これに対してシンプルなPOSTリクエストを受け入れるため、間に自動化プラットフォームを挟む必要はありません。

この例では、WordPress上の**FluentCRM**を使用します。「インバウンドWebhook」や「購読者の作成」エンドポイントを提供する他のツールでも、構成は同じです。

**まず、CRMからURLを取得します。** WordPressで **FluentCRM → 設定 → インバウンドWebhook** を開き、Webhookを作成します。新しい連絡先に適用するリスト、タグ、購読ステータスを選択し、生成されたWebhook URLをコピーします。ここで設定した内容はすべて自動的に適用されるため、ボットはメールアドレスを送信するだけで済みます。

**次に、カスタム関数を設定します：**

**基本情報:**
- **名前:** `add_newsletter_subscriber`
- **説明:** "チャットで提供されたメールアドレスを使用して、ニュースレターリストに登録する"
- **AIアクション:** "連絡先がニュースレターの購読に同意し、メールアドレスを提供した瞬間にこれを使用してください。実際にアドレスが提供される前に呼び出したり、同じ人物に対して二度呼び出したりしないでください。"

**接続:**
- **URL:** CRMからコピーしたWebhook URL
- **メソッド:** POST

**入力パラメータ:**
- `email` (文字列、必須): "会話の中で連絡先が提供したメールアドレス"
- `first_name` (文字列、任意): "連絡先が言及した場合の、その人の名"

**システムデータをスキップ:** これを**オン**にします。CRMには上記のフィールドのみが必要であり、ペイロードを軽量化することで、予期しないフィールドを拒否するツールでのエラーを回避できます。

**レスポンスマッピング:** ここでは不要です。ボットが処理を継続するために戻り値を受け取る必要はありません。

**会話を実行するエージェントに対して関数を有効にすることを忘れないでください**（[エージェントへの関数の割り当て](#assigning-functions-to-an-agent)を参照）。これは、正しく構築された関数が実行されない最も一般的な理由です。

::: tip
**ヒント:** ボットには組み込みの **連絡先メールアドレスの更新** ツールもあり、プラットフォーム内の連絡先レコードにアドレスを保存します。これはこの関数とは別のものであり、併用すると便利です。組み込みツールは自身の連絡先レコードを完全な状態に保ち、カスタム関数はそのアドレスをCRMに送信します。
:::


---

## 信頼性の高いカスタム関数を作成するためのヒント

1. **繰り返しリクエストが安全であることを確認する。** 同じリクエストが誤って2回送信された場合でも、重複したレコードが作成されないようにする必要があります。ネットワークの不具合により、このような事態が発生することがあります。

2. **明確なエラーメッセージを返す。** システム側で何らかの問題が発生した場合は、人間が理解できるエラーメッセージを返してください。ボットがそれを顧客に適切に伝えます。

3. **応答時間を10秒以内に抑える。** システムの処理に時間がかかる場合は、まず簡単な応答を返すことを検討してください。

4. **期限切れや無効な認証情報を処理する。** APIキーの有効期限が切れた場合は、ボットが再試行せずに人間に通知できるよう、明確なエラーメッセージを表示するようにしてください。

5. **詳細な説明を記述する。** AIは、いつ関数を呼び出し、会話からどのように適切な情報を抽出するかを判断するために、あなたの記述を使用します。説明が曖昧だと、誤った結果につながります。

6. **実際の会話でテストする。** 「試用（Try Out）」は初期テストには最適ですが、最初の数件のライブ会話を監視して、実際の顧客の問い合わせで問題なく動作することを確認してください。

7. **ログを保持する。** アプリから送信されるリクエストを記録するよう開発者に依頼し、問題が発生した際に迅速にデバッグできるようにしてください。

8. **公開されている最終URLを使用する。** 関数のURLは、公開されているWeb（HTTP/HTTPS）アドレスである必要があります。内部アドレス、localhost、プライベートネットワークのアドレスはセキュリティ上の理由から拒否されます。また、プラットフォームはリダイレクトを追跡しないため、リダイレクト先のURLではなく、最終的なURLを直接指定してください。

---

## 実行制限

すべてのカスタム関数には、エディターの下部にオプションの **実行制限** セクションがあります。これは、AIが関数を実行できる頻度や、以前の結果を再利用できるかどうかを制御します。ここにある設定はすべてオプションです。すべて空のままにすれば、関数はこれまで通りに動作します。


**読み取り専用関数。** 関数がデータの「読み取り」（株価検索、価格チェック、注文状況検索など）のみを行い、データの作成や変更を一切行わない場合にオンにします。一時的なネットワーク障害によってAIの返信が中断された場合、プラットフォームは顧客に回答を返せないままにするのではなく、安全に会話のターンを再試行できます。関数が絶対に書き込みを行わない場合にのみ有効にしてください。レコードを作成する関数はオフのままにする必要があります。そうしないと、再試行によって誤って2回実行される可能性があるためです。

**繰り返し呼び出し時にキャッシュされた結果を返す。** AIが同じ入力で関数を再度呼び出した場合（例：顧客が同じ質問を2回した場合）、エンドポイントを再度呼び出す代わりに、以前の結果が再利用されます。キャッシュされた結果は最大24時間保持されます。入力が「異なる」呼び出しは、常にエンドポイントへ新しく送信されます。

**会話ごとの最大実行回数。** 1つの会話内で関数を実行できる回数の上限です。見積もりの生成、コールバックのトリガー、自動化の開始など、チャットごとに1回だけ実行すべき関数には「1」を設定します。上限に達すると、AIには関数がすでに実行済みであることが伝えられ、最新の結果が提供されるため、AIは沈黙することなく顧客に回答を続けることができます。

**時間枠ごとの最大実行回数。** 時間経過に基づくレート制限です（例：60分間に最大5回）。有料のサードパーティサービスを呼び出したり、負荷の高い自動化をトリガーしたりする関数に役立ちます。両方のボックスを併せて入力する必要があります（実行回数と、最大7日までの分単位の時間枠）。

いくつか知っておくべきこと:

- 制限は「成功した」実行のみをカウントします。エンドポイント側で失敗した呼び出しは、予算を消費しません。
- 制限によって実行がブロックされた場合でも、顧客が放置されることはありません。AIにはその理由が伝えられ、すでに持っている情報を使って対応します。
- 制限は、関数が実行されるすべての場所（すべてのチャネルでの通常のチャット、および自動化によって管理される関数）に適用されます。「試用（Try Out）」でのテスト会話はカウントされず、制限も適用されません。

---

## 組み込みボットツール

自身で構築するカスタム関数に加え、プラットフォームにはAIボットが会話中に使用できる組み込みツールライブラリが用意されています。これらは、チームメンバーへの通知、予約の作成、連絡先へのタグ付け、Webサイトの検索、フォローアップのスケジュール設定など、ボットが必要とする一般的な機能を網羅しているため、ゼロから構築する必要はありません。

**ボットは、会話で何が起こっているか、およびエージェント（および紐付いているキャンペーン）がどのように設定されているかに基づいて、各ツールを使用するタイミングを決定します。** これらのツールのほとんどは、関連機能が有効になると自動的にオンになります（たとえば、予約ツールは、カレンダーを接続して予約を有効にすると初めて利用可能になります）。

**クレジットコスト:** 各ツール呼び出しはエージェントのAI品質ティアに基づいて課金され、自分で構築したカスタム関数も同様に課金されます：

| AI品質ティア | ツール呼び出しあたりのクレジット | 独自のAnthropicキー（BYOK）を接続している場合 |
|---|---|---|
| Pro | 1クレジット | 0クレジット — 独自のキーで実行 |
| Economy (非推奨) | 0.5クレジット | 0クレジット — 独自のキーで実行 |
| Max | 0.25クレジット | 0.25クレジット — 独自のキーを接続していても課金されます（Maxは当社のモデルで実行されるため） |
| Mini | 0.15クレジット | 0.15クレジット — 独自のキーを接続していても課金されます（Miniは当社のモデルで実行されるため） |

### チームおよびタスクツール

| ツール | 機能 | ボットが使用するタイミング |
|------|--------------|----------------------|
| **チームメンバーに通知** | この連絡先に対するボットを一時停止し、人間の対応が必要であることをチームにメールで通知します。チャットにはフラグが立てられ、チームメイトが引き継げるようになります。 | 顧客が人間の対応を求めたとき、不満を感じているとき、またはボットが回答を許可されていない、あるいは回答できない質問をしたとき。 |
| **タスクを作成** | タスクボードに新しいタスクを作成し、必要に応じて連絡先や会話にリンクします。ボットは通常通り返信を続けます。タスクはチームがフォローアップするためのメモとして機能します。 | 機能リクエスト、アップセルの機会、チームが後で対応すべき折り返し連絡など、緊急ではない項目。 |
| **FAQの更新を提案** | ボットがうまく回答できない質問に遭遇したとき、ナレッジベースに回答を追加するようチームに求めるタスクを作成します。 | 既存のFAQでカバーされていない質問を連絡先がしたとき。次回のために不足分を修正するため。 |
| **FAQ提案にコンテキストを追加** | 別の連絡先が後で異なる角度から同様の質問をした場合、ボットは重複するタスクを作成する代わりに、既存のFAQ提案にそのコンテキストを追加します。 | 自動 — 複数の人が同じ知識のギャップを指摘したときに、タスクリストを整理された状態に保ちます。 |

### 連絡先ツール

| ツール | 機能 | ボットが使用するタイミング |
|------|--------------|----------------------|
| **タグ付け** | ボットの各応答後に自動的に実行されます。顧客向けのボットが呼び出しを決定するツールではありません。システムが最近の会話を確認し、関連するタグを適用します。可能な限り既存のタグを再利用し、必要な場合にのみ新しいタグを作成します。 | 自動 — 興味、意図、リードの質、言語など、セグメント化する価値のある情報が会話から明らかになったとき。 |
| **連絡先名の更新** | 顧客が名前を共有した際に、名や姓を保存します。 | 顧客が自己紹介をしたとき、または名前を訂正したとき。 |
| **連絡先メールアドレスの更新** | 顧客がメールアドレスを共有した際に、それを保存します。 | 顧客がニュースレター、領収書、アカウント検索などのためにメールアドレスを提供したとき。 |

### 予約・アポイントメントツール

これらのツールは、エージェントにリンクされたキャンペーンで予約が有効になっており、カレンダーイベントタイプが設定されている場合にのみ利用可能です。

| ツール | 機能 | ボットの使用タイミング |
|------|--------------|----------------------|
| **空き時間の確認** | 指定された日付や期間に対して、接続されたカレンダーで空いている時間枠を検索します。 | 顧客が予約を希望し、ボットが実際の空き状況を提示する必要がある場合。 |
| **アポイントメントの予約** | カレンダーにアポイントメントを作成し、顧客に予約完了を通知します。 | 顧客が特定の日時を確定した後。 |
| **アポイントメントの変更** | 既存のアポイントメントを別の日時に再スケジュールします。 | 顧客が再スケジュールを依頼した場合。 |
| **アポイントメントのキャンセル** | 既存のアポイントメントをキャンセルします。 | 顧客がキャンセルを依頼した場合。 |
| **アポイントメントの検索** | 連絡先の既存のアポイントメントを呼び出し、すでに予約されている内容をボットが把握できるようにします。 | 顧客が「予約はいつですか？」と尋ねた場合や、再スケジュールの提案前。 |

### ナレッジ・Webツール

| ツール | 機能 | ボットの使用タイミング |
|------|--------------|----------------------|
| **ウェブサイトの検索** | キャンペーンの動的URLリストに追加されたURLをスキャンし、顧客の質問に対する回答となる製品ページ、記事、その他のコンテンツを見つけます。**AIウェブ検索**がオンになっており、少なくとも1つの動的URLを追加している場合にのみ利用可能です。AIウェブ検索がオフの場合、顧客がチャットに貼り付けたリンクであっても、ボットはページやリンクを読み取ることができません。 | 顧客が製品、価格、場所、ポリシーなど、ウェブサイトに掲載されている可能性が高い内容について質問したとき。 |
| **リンクの確認** | 特定のURLの内容を読み取り、そのページに関する質問にボットが回答できるようにします。**AIウェブ検索**がオンになっており、少なくとも1つの動的URLを追加している場合にのみ利用可能です。AIウェブ検索がオフの場合、顧客がチャットに貼り付けたリンクであっても、ボットはページやリンクを読み取ることができません。 | 顧客がリンクを共有したとき、またはサイト上の特定のページについて質問したとき。 |
| **ウェブ検索** | 公開されているGoogle検索を実行して上位の結果を返すため、ボットは自身のコンテンツ以外の質問にも回答できます。 | 顧客がナレッジベースに含まれていない一般的な内容（例：道順、公開情報）について質問したとき。ウェブ検索が有効な場合にのみ使用されます。 |

### フォローアップツール

これらのツールを使用するには、エージェントにリンクされているキャンペーンでフォローアップを有効にする必要があります。

| ツール | 機能 | ボットの使用タイミング |
|------|--------------|----------------------|
| **スマートフォローアップのスケジュール** | フォローアップシーケンスを使用してインテリジェントなフォローアップメッセージをスケジュールします。会話に基づいて適切なテンプレートとタイミングを選択します。 | 顧客からの返信が途絶えたとき、またはボットに「後で確認して」と依頼したとき。 |
| **フォローアップのスケジュール** | 特定の時間に基本的なフォローアップをスケジュールします。 | ボットが特定のタイミングで会話を促す必要があるとき。 |

### カスタム関数実行ツール

| ツール | 機能 | ボットの使用タイミング |
|------|--------------|----------------------|
| **カスタム関数の実行** | 作成してエージェントに割り当てたカスタム関数のいずれか（このページの残りの部分を参照）を実行します。 | 顧客のリクエストが、カスタム関数の目的と一致したとき。 |

### レストラン予約ツール (ZenchefおよびFormitable)

これらのツールは、ZenchefまたはFormitableの統合が接続されている場合にのみ使用できます。ボットがレストランの予約をエンドツーエンドで管理できるようになります。

| ツール | 機能 | ボットの使用タイミング |
|------|--------------|----------------------|
| **レストランの空き状況確認** | 指定された日付、人数、および（オプションで）座席エリアの空き予約枠を検索します。 | ゲストがテーブルの予約を希望した場合。 |
| **レストラン予約の作成** | 新規予約を作成します。 | ゲストが特定の時間枠を確定した後。 |
| **レストラン予約の更新** | 既存の予約の日付、時間、人数、またはメモを変更します。 | ゲストが予約の変更を依頼した場合。 |
| **予約のキャンセルまたはステータス変更** | 予約をキャンセルするか、ステータス（確定、ノーショーなど）を更新します。 | ゲストがキャンセルした場合、またはボットがステータスの変更を記録する必要がある場合。 |
| **予約の検索** | 名前、メールアドレス、日付などの条件に一致する既存の予約を検索します。 | リピーターのゲストが既存の予約について尋ねた場合。 |
| **ゲストプロファイルの更新** | レストランシステム内のゲストプロファイル（好み、メモ、連絡先情報など）を更新します。 | ゲストが食事の好み、新しい電話番号、その他のプロファイルレベルの情報を共有した場合。 |
| **レストラン製品リストの取得** | 予約可能なメニュー、セットメニュー、またはアドオンのリストを取得します。 | ゲストが「どんなセットメニューがありますか？」と尋ねた場合や、ボットが予約にメニューを添付する必要がある場合。 |

### ツールのオン/オフの切り替え

ほとんどのツールは、エージェントの**AI機能**タブ（従来のキャンペーンで作業している場合は、キャンペーンの**AI機能**ステップ）で制御されます。

- **予約ツール**は、予約を有効にしてカレンダーを接続するとオンになります。これは現時点ではキャンペーンごとの設定であり、エージェントのAI機能タブからそのキャンペーンのステップへ直接リンクされています。
- **フォローアップツール**は、フォローアップを有効にするとオンになります。
- **レストランツール**は、ZenchefまたはFormitableアカウントを接続するとオンになります。
- **ウェブ検索**は、**FAQとナレッジ**タブに専用の切り替えスイッチがあります。
- **タスクツール**は、**AIによるタスク作成を許可する**スイッチでエージェントごとにオフにできます（デフォルトではオンになっています。**設定 → プロフィール → 機能**にあるアカウント全体のタスクスイッチは、すべての場所でタスクシステム全体をオフにします）。
- **連絡先更新ツール**は、同じ**AI機能**タブで制御されます。AIが連絡先の名前を変更したり、収集した追加情報を保存したりできるかどうかを設定します。
- **アラートツール**は常に利用可能です。**タグ付け**はボットの各返信後に自動的に実行されます（これはボットが呼び出すことを選択するツールではありません）。

ボットに特定の組み込みツールを使用させたくない場合は、基盤となる機能を無効にするのが最も確実な方法です（例：予約をオフにすると、すべての予約ツールが無効になります）。

---

## オートメーションによって管理される関数

「カスタム関数」ページの一部のエントリには、**「オートメーションによって管理」**というバッジが表示されることがあります。これらはこのページで作成されたものではなく、**「AIエージェント関数」**トリガーを持つオートメーションから生成されたものです。これにより、外部のWebアドレスを指定する代わりに、オートメーションキャンバス上でステップを視覚的に構築して、エージェントに機能を持たせることができます。

管理対象関数は、システムによって自動的に管理されます。その名前、説明、フィールドは常にオートメーションのトリガー設定に従うため、このページから編集や削除を行うことはできません。変更が必要な場合は、**Open automation**（オートメーションを開く）リンクを使用して、オートメーション自体を編集してください。ただし、どのエージェントにその機能を持たせるかは、通常通り選択可能です。エージェントの **AI Abilities**（AI機能）タブでは、他の機能と並んで表示され、通常のオン/オフ切り替えスイッチで設定できます（オートメーションが一時停止されている場合はその旨が表示され、オートメーションが有効になると機能も利用可能になります）。それ以外の動作は他のカスタム関数と同様で、AIが呼び出すタイミングを判断し、定義された詳細情報を収集し、同じ会話内でオートメーションの返信を利用することができます。

どちらを選択するか迷っている場合：すでに呼び出し先のアドレスがあるシステムには通常のカスタム関数を指定してください。スプレッドシートやデータベースの検索、条件分岐、レコード作成など、サーバーを自分で運用せずにステップを組み合わせて作業を行いたい場合は、AIエージェント関数のトリガーを使用した自動化を構築してください。詳細は[自動化](../automations/automations.md#letting-your-ai-agent-call-an-automation)を参照してください。

---

## プランの要件

カスタム関数は、カスタム関数機能が含まれているプランで利用可能です。サブスクリプションを確認して、利用可能かどうかを確認してください。

---

## 次のステップ

- [MCPサーバーをボットに接続する](mcp-servers.md) — 関数を1つずつではなく、ツールをまとめて利用できます。
- [AIエージェント](../ai-agents/ai-agents.md) — カスタム関数が属するAI Studioグループのメインページであり、カスタム関数をボットに割り当てる場所です。
