> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/ja/serve/customer-service-system-integration.md).

# 外部カスタマーサポートシステムとの連携（有人対応への引き継ぎを含む）

カスタマーサポートシステムやチャットプラットフォームから API で MaiAgent を AI エンジンとして利用するためのエンドツーエンド仕様です。メッセージの送受信、AI が有人対応を必要と判断した際の自社オペレーターへの引き継ぎ、対応終了後の AI への復帰を説明します。

このページは、すでに自社のカスタマーサポートシステムやチャット画面を持ち（自社 Web サイト、LINE、Messenger などのチャネルを自社側に接続している場合）、MaiAgent を **AI エンジン**として利用したい連携担当者向けです。訪問者のメッセージを自社システムから MaiAgent に送り、AI の返信を自社システムで受け取ります。AI が有人対応を必要と判断した場合は、**自社のオペレーター**が引き継ぎ、対応終了後に会話を AI に戻します。

連携には MaiAgent の既存の公開 API と 2 系統の Webhook のみを使用します。個別のカスタマーサポートシステム向けに専用インターフェースを開発する必要はありません。

## 2 つの連携シナリオ <a href="#scenarios" id="scenarios"></a>

| シナリオ                                  | 訪問者が会話する場所                                                     | オペレーターが対応する場所 | 連携方法                                                                  |
| ------------------------------------- | -------------------------------------------------------------- | ------------- | --------------------------------------------------------------------- |
| **シナリオ A**：MaiAgent を AI エンジンとして利用します | 自社システム（自社 Web サイト、LINE などのチャネルを自社側に接続します）                      | 自社システム        | [事前設定](#setup)の後、[ステップ 1](#step-identity)～[ステップ 6](#step-return)に従います |
| **シナリオ B**：オペレーターのみが自社システムを利用します      | MaiAgent の会話プラットフォーム（Web Chat、LINE 公式アカウントなどを MaiAgent に接続します） | 自社システム        | [事前設定](#setup)の後、[シナリオ B](#scenario-b)に従います                           |

オペレーターが Genesys Cloud を利用している場合、シナリオ B では組み込みの [Genesys Cloud 連携](/tech/ja/serve/customer-service-system-integration/genesys-cloud-integration.md)を利用でき、自社で連携を構築する必要はありません。

どちらのシナリオも、有人対応への引き継ぎイベント、[イベント一覧](#events)、[状態の照会](#query-state)は共通です。以下の連携概要とステップ 1～6 では、シナリオ A を説明します。

## 連携の全体像 <a href="#overview" id="overview"></a>

```mermaid
sequenceDiagram
    participant V as 訪問者
    participant S as 自社カスタマーサポートシステム
    participant M as MaiAgent
    participant H as 自社オペレーター

    V->>S: メッセージを送信します（Web / LINE / …）
    S->>M: ① ID を同期します（sourceId → contactId）
    S->>M: ② 会話を作成します（初回）
    S->>M: ③ メッセージを送信します POST /messages/
    M-->>S: 201（AI の返信は非同期です）
    M-)S: ④ Outgoing Webhook：AI の返信
    S->>V: AI の返信を表示します

    Note over M: AI が有人対応を必要と判断します
    M-)S: ⑤ handoff.requested
    S->>H: チケットを作成し、オペレーターを割り当てます
    H->>V: オペレーターが対応を引き継ぎます（自社システム内）
    S->>M: ⑥ PATCH /conversations/{id}/return-to-ai/
    M-)S: handoff.returned_to_ai
    Note over M: 以降のメッセージへの AI の返信を再開します
```

### 双方の役割 <a href="#responsibilities" id="responsibilities"></a>

| 担当           | 役割                                                                                                             |
| ------------ | -------------------------------------------------------------------------------------------------------------- |
| **自社システム**   | チャネル接続、訪問者向け画面、チケットとオペレーター席、会話履歴の保存と表示を担当します。訪問者のメッセージを MaiAgent に送り、Webhook を受信し、有人対応終了時に AI への復帰 API を呼び出します |
| **MaiAgent** | AI の返信、会話コンテキストの維持、LLM による有人対応への引き継ぎ判定、有人対応への引き継ぎと AI への復帰イベントの送信を担当します                                        |

## 事前設定 <a href="#setup" id="setup"></a>

以下はすべて MaiAgent の管理画面で行います。会話プラットフォームごとに一度設定します。

### 1. Web Chat 会話プラットフォームを作成し、認証情報を取得します <a href="#setup-inbox" id="setup-inbox"></a>

API 連携には **Web Chat** タイプの会話プラットフォームを使用します。次の情報が必要です。

* **API キー**：取得方法は[クイックスタート](/tech/ja/api-integration/quickstart.md)を参照してください。
* **Web Chat ID**：<mark style="color:blue;">カスタマーサポート会話</mark> → <mark style="color:blue;">会話プラットフォーム</mark> → 対象の API プラットフォームを編集 → <mark style="color:blue;">連携とログイン</mark> → <mark style="color:blue;">Webhook 設定</mark>の最下部にある<mark style="color:blue;">API 情報</mark>カードで確認できます。読み取り専用で、コピーできます。ユーザーマニュアルの[会話プラットフォームの基本設定](https://docs.maiagent.ai/build/conversation-settings/platform-settings/basic-settings#web-chat-id)を参照してください。

### 2. Outgoing Webhook を設定します（AI の返信を受信します） <a href="#setup-outgoing-webhook" id="setup-outgoing-webhook"></a>

<mark style="color:blue;">カスタマーサポート会話</mark> → <mark style="color:blue;">会話プラットフォーム</mark> → 対象のプラットフォームを編集 → <mark style="color:blue;">Webhook 設定</mark> → <mark style="color:blue;">Webhook を追加</mark>を選択します。タイプは **Outgoing** を選び、エンドポイントに自社の返信受信 URL を入力します。形式は **MaiAgent 標準形式**を選択します。自社システムで固定の JSON 構造が必要な場合は、**カスタムテンプレート**を選択します。フィールドと payload は [Webhook](/tech/ja/serve/webhook.md) を参照してください。

### 3. オペレーターへの引き継ぎを有効にします <a href="#setup-handoff" id="setup-handoff"></a>

同じ会話プラットフォームの<mark style="color:blue;">有人対応への引き継ぎ設定</mark>を開きます。各フィールドの意味と操作画面は、ユーザーマニュアルの[有人対応への引き継ぎ設定](https://docs.maiagent.ai/build/conversation-settings/human-handoff)を参照してください。オペレーターが自社システムで対応する場合は、次の設定を推奨します。

| 設定                                                                                          | オペレーターが自社システムで対応する場合の推奨設定                                                                                                                                                                                                                                                                                  |
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <mark style="color:blue;">オペレーターへの引き継ぎを有効化</mark>                                           | 有効にします                                                                                                                                                                                                                                                                                                     |
| <mark style="color:blue;">有人対応への引き継ぎ条件</mark>の判定ルール（<mark style="color:blue;">ロール指示</mark>） | まずはデフォルトのルールを使用します。訪問者が明示的に有人対応を求めた場合、AI で対応できない問題、訪問者の感情が悪化した場合、人による確認が必要な請求・アカウント関連操作が対象です。その後、キーワードの追加や確信度が低い場合の引き継ぎなど、業務に合わせて調整します                                                                                                                                                                     |
| <mark style="color:blue;">割り当て設定</mark> → <mark style="color:blue;">割り当てモード</mark>          | **引き受け方式**を選択します。MaiAgent は管理画面のメンバーに会話を割り当てません。会話は待機キューに残り、自社システムが引き継ぎます                                                                                                                                                                                                                                  |
| <mark style="color:blue;">割り当て設定</mark> → <mark style="color:blue;">待機タイムアウト</mark>         | **タイムアウトなし**にチェックを入れます（引き受け方式のみ選択できます）。AI への復帰 API を呼び出すまで会話は待機キューに残ります。MaiAgent が自動的に AI に戻すことはありません                                                                                                                                                                                                      |
| <mark style="color:blue;">割り当て設定</mark> → <mark style="color:blue;">キュー上限</mark>            | オペレーターの対応能力に合わせて設定します（1～500）。上限に達すると、新たな有人対応への引き継ぎリクエストは発生しません。そのメッセージには AI の返信がなく、`handoff.requested` も送信されません                                                                                                                                                                                            |
| <mark style="color:blue;">対応時間</mark>                                                       | 必要に応じて有効にします。<mark style="color:blue;">オフラインメッセージを表示</mark>の場合、対応時間外は有人対応に引き継ぎません。そのメッセージには AI の返信がなく、`handoff.requested` も送信されません（オフラインメッセージは Web Chat のフロントエンドにのみ送信されるため、時間外の案内は自社システムで処理してください）。<mark style="color:blue;">メッセージを受け付ける</mark>の場合は、待機キューに入り `handoff.requested` が送信されますが、待機タイムアウトは開始されません |

API で会話プラットフォームを設定する場合、引き受け方式とタイムアウトなしは `dispatchMode: "handover"` と `assignmentQueueTimeout: 0` に対応します。

{% hint style="danger" %}
**自動割り当てモードでは、待機タイムアウトを 0 に設定しないでください。** 自動割り当て（デフォルト）の待機タイムアウトに指定できる値は 1～3600 秒のみです。画面で 0 を入力すると範囲外の警告が表示され、API で 0 を送信するとデフォルトの 300 秒に変更されます。300 秒以内に MaiAgent のメンバーが引き継がない場合、MaiAgent は `handoff.queue_timeout` を送信して会話を AI に戻します。訪問者も自社のオペレーターも、この切り替えに気付きません。
{% endhint %}

{% hint style="warning" %} <mark style="color:blue;">引き継ぎ通知メッセージ</mark>や<mark style="color:blue;">キュー待機案内</mark>などの訪問者向け案内文は、MaiAgent 自身の Web Chat フロントエンドに送信され、**Webhook 経由では自社システムに送信されません**。`handoff.requested` を受信した際に、自社システムで「オペレーターにおつなぎしています」などの案内を訪問者に表示してください。
{% endhint %}

### 4. 有人対応への引き継ぎ Webhook を有効にします <a href="#setup-handoff-webhook" id="setup-handoff-webhook"></a>

同じタブのサブタブ<mark style="color:blue;">通知</mark>を開き、<mark style="color:blue;">Webhook 通知（システム連携）</mark>を有効にして、次の情報を入力します。

* <mark style="color:blue;">Webhook URL</mark>：HTTPS のみ使用できます。
* <mark style="color:blue;">署名シークレット（任意）</mark>（設定を推奨します）：設定すると、各送信に HMAC-SHA256 署名が付与されます。検証方法は[送信と署名](#handoff-delivery)を参照してください。

<mark style="color:blue;">Email 通知</mark>と<mark style="color:blue;">通知センターのお知らせ</mark>は、会話が MaiAgent のメンバーに割り当てられた場合にのみ送信されます。この連携では使用しないため、無効にできます。

{% hint style="info" %}
この 3 つの通知スイッチは、会話プラットフォームの管理者が管理画面で有効にします。別途申請する必要はありません。操作画面はユーザーマニュアルの[有人対応への引き継ぎ通知](https://docs.maiagent.ai/build/conversation-settings/human-handoff/handoff-notification)を参照してください。
{% endhint %}

## ステップ 1：訪問者の ID を対応付けます <a href="#step-identity" id="step-identity"></a>

自社システムのユーザー ID を指定して ID 同期 API を呼び出し、訪問者の MaiAgent 側の `contactId` を取得します。

```bash
curl -X POST \
  'https://api.maiagent.ai/api/v1/web-chats/{webChatId}/setup-contact-credentials/' \
  -H 'Content-Type: application/json' \
  -d '{ "sourceId": "your-user-id", "name": "王小明" }'
```

```json
{ "contactId": "c0ffee00-1111-2222-3333-444455556666" }
```

同じ `sourceId` で繰り返し呼び出すと、同じ `contactId` が返されます（冪等です）。`sourceId ↔ contactId` の対応を自社のユーザーデータに保存してください。`sourceId` には推測できない値を使用してください。詳細は[連絡先 ID の同期と Token の更新](/tech/ja/serve/contacts/contact-credentials-sync.md)を参照してください。

## ステップ 2：会話を作成します <a href="#step-conversation" id="step-conversation"></a>

訪問者ごとに 1 つの会話を作成し、**長期間継続して使用します**。MaiAgent は会話単位でコンテキストを維持します。

```bash
curl -X POST 'https://api.maiagent.ai/api/v1/conversations/' \
  -H 'Authorization: Api-Key <自社のAPIキー>' \
  -H 'Content-Type: application/json' \
  -d '{ "webChat": "<Web Chat ID>", "contact": "<contactId>" }'
```

レスポンスの `id`（会話 ID）と `inbox.id`（会話プラットフォーム ID。Webhook の設定時に使用します）を記録してください。レスポンスのフィールドは[会話とメッセージの作成](/tech/ja/api-integration/conversations-and-messages.md)を参照してください。

訪問のたびに新しい会話を開始したい場合（チケットのクローズ後など）は、新しい会話を作成します。以前の会話履歴は保持されます。

## ステップ 3：訪問者のメッセージを送信します <a href="#step-send" id="step-send"></a>

```bash
curl -X POST 'https://api.maiagent.ai/api/v1/messages/' \
  -H 'Authorization: Api-Key <自社のAPIキー>' \
  -H 'Content-Type: application/json' \
  -d '{
    "conversation": "<会話 ID>",
    "content": "注文の状況を確認したいです",
    "attachments": []
  }'
```

`201` レスポンスは、メッセージが作成されたことのみを示します。**AI の返信は数秒以内に Outgoing Webhook で送信されます**（ステップ 4）。HTTP レスポンス自体には返信は含まれません。添付ファイルは先にアップロードして添付オブジェクトを取得し、`attachments` に指定してください。[Presigned ファイルアップロード方式](/tech/ja/api-integration/api_knowledge.md)を参照してください。

## ステップ 4：AI の返信を受信します <a href="#step-receive" id="step-receive"></a>

AI の返信が作成されると、MaiAgent は設定した Outgoing Webhook にリクエストを送信します。標準形式では、エンドポイントは次のようなデータを受信します。

```json
{
  "id": "2491074a-6d23-4289-af45-caa12531420e",
  "type": "outgoing",
  "content": "ご注文 #12345 は現在配送中で、明日到着予定です。",
  "created_at": "2026-09-09T10:15:30.123456+00:00",
  "conversation": {
    "id": "8e44604a-8278-4c96-96b5-3e5a0548d738",
    "status": "open",
    "progress_status": "ai_processing",
    "auto_reply_enabled": true,
    "assignee": null
  },
  "contact": { "id": "c0ffee00-1111-2222-3333-444455556666", "name": "王小明" },
  "sender": { "id": "…", "name": "AI カスタマーサポート", "type": "chatbot" },
  "attachments": []
}
```

自社システムで `contact.id` から対応するユーザーを、`conversation.id` から会話を特定し、`content` と添付ファイルを自社チャネルの形式に変換して訪問者に送信します。2xx を返してください。全フィールド、カスタムテンプレート、送信動作は [Webhook](/tech/ja/serve/webhook.md) を参照してください。

{% hint style="info" %}
payload 内で自社のユーザー ID やダウンロード可能な添付ファイル URL を直接取得するには、**カスタムテンプレート**で `contact.source_id` と `attachment.file.url` を出力します。例は [Webhook › カスタムテンプレート](/tech/ja/serve/webhook.md#custom-template)を参照してください。
{% endhint %}

## ステップ 5：AI が有人対応への引き継ぎを判断します <a href="#step-handoff" id="step-handoff"></a>

訪問者のメッセージを受信するたびに、MaiAgent はまず判定モデルで有人対応が必要かを判断します。必要と判断した場合は、次のように処理します。

1. 会話の状態が `queued` になり、`auto_reply_enabled` が `false` になります。**このメッセージには AI の返信がありません**。以降のメッセージにも AI は返信しません。
2. MaiAgent は自社の有人対応への引き継ぎ Webhook URL に `handoff.requested` イベントを送信します。

### イベント payload <a href="#handoff-payload" id="handoff-payload"></a>

フィールド一覧と JSON の例は、API ドキュメントの[有人対応への引き継ぎ Webhook イベント](https://docs.maiagent.ai/api/preparation/handoff-webhook)の「イベント形式」を参照してください。このフローの連携では、次の点を把握してください。

* 4 種類のイベントはすべて同じフィールドを持ちます。`event` に応じて処理を分岐してください（下記の[イベント一覧](#events)を参照してください）。
* `conversation.id` と `contact.id` は、ステップ 1、2 で記録した会話と訪問者に対応します。
* イベントの `id` で重複を排除し、`occurred_at` で順序を判断します。payload には識別情報のみが含まれ、会話の内容は含まれません。
* `assignee` はイベント発生時に割り当てられている MaiAgent のメンバーです。`handoff.requested` および自社のオペレーターが引き継ぐ場合は常に `null` です。
* フィールド名とネスト構造はステップ 4 のメッセージ Webhook と同じなので、同じ受信エンドポイントで両系統の送信を処理できます。

### 送信と署名 <a href="#handoff-delivery" id="handoff-delivery"></a>

`POST`、`Content-Type: application/json` で送信し、タイムアウトは 10 秒です。2xx 以外のレスポンスまたは接続失敗の場合、**60 秒ごとに最大 3 回再試行します**。署名シークレットが設定されている場合、リクエストに `X-MaiAgent-Signature-256: sha256=<hex>` が付与されます。値は、シークレットを用いて元のリクエスト本文に対して計算した HMAC-SHA256 です。検証コードとそのまま起動できる受信エンドポイントの例は、API ドキュメントの[有人対応への引き継ぎ Webhook イベント](https://docs.maiagent.ai/api/preparation/handoff-webhook)の「署名検証」と[最小受信エンドポイントの例](https://docs.maiagent.ai/api/preparation/handoff-webhook#receiver-example)を参照してください。

### 自社システムで `handoff.requested` を受信した後の処理 <a href="#after-triggered" id="after-triggered"></a>

* 自社システムでチケットを作成し、オペレーターを割り当て、訪問者に引き継ぎ案内を表示します。
* 以降、訪問者のメッセージは自社システム内でオペレーターが処理します。**MaiAgent への送信を停止しても構いません**。MaiAgent に完全な履歴を保持したい場合は、引き続き `POST /messages/` を呼び出せます。メッセージは会話に保存され、Incoming Webhook が発生しますが、AI に戻るまで AI の返信は生成されません。
* オペレーターの返信は、自社システムから直接訪問者に送信します。MaiAgent を経由する必要はありません。

## ステップ 6：有人対応終了後に AI に戻します <a href="#step-return" id="step-return"></a>

チケットの対応が終了したら、AI への復帰 API を呼び出します。

```bash
curl -X PATCH 'https://api.maiagent.ai/api/v1/conversations/{conversationId}/return-to-ai/' \
  -H 'Authorization: Api-Key <自社のAPIキー>'
```

会話が `open` に戻り、`auto_reply_enabled` が `true` に復帰します。MaiAgent は `handoff.returned_to_ai` を送信し、以降の訪問者のメッセージには AI が再び返信します。レスポンスは更新後の会話オブジェクトです。

{% hint style="warning" %}
API キーを所有するメンバーには、対象の会話プラットフォームの会話アクセス権限が必要です。[事前設定](#setup-handoff)に従って引き受け方式を選択し、<mark style="color:blue;">タイムアウトなし</mark>にチェックを入れていない場合、<mark style="color:blue;">待機タイムアウト</mark>の満了時に MaiAgent は自動的に AI に戻し、`handoff.queue_timeout` を送信します。この動作が自社のフローに合っているか確認してください。対応時間外に<mark style="color:blue;">メッセージを受け付ける</mark>で待機キューに入った会話は、**待機タイムアウトが開始されません**。必ず自社システムから `return-to-ai` を呼び出して終了する必要があります。
{% endhint %}

## シナリオ B：訪問者は MaiAgent の会話プラットフォーム、オペレーターは自社システムを利用します <a href="#scenario-b" id="scenario-b"></a>

訪問者は MaiAgent の会話プラットフォームで Agent と会話し、有人対応への引き継ぎ後のみ、オペレーターが自社のカスタマーサポートシステムから返信します。訪問者のメッセージは最初から MaiAgent に入るため、自社システムでステップ 1～3 を実施する必要はありません。代わりに、メッセージ Webhook で有人対応中のメッセージを自社システムに取り込み、API でオペレーターの返信を会話に書き戻して、双方向に同期します。

事前設定は訪問者が利用する会話プラットフォームで行います。[オペレーターへの引き継ぎの有効化](#setup-handoff)（引き受け方式＋タイムアウトなし）と[有人対応への引き継ぎ Webhook の有効化](#setup-handoff-webhook)はシナリオ A と同じです。[メッセージ Webhook](#setup-outgoing-webhook)には **Incoming**（訪問者のメッセージ）と **Outgoing**（Agent またはオペレーターの返信）の両方向を追加します。オペレーターの返信の書き戻しと AI への復帰には API キーが必要です。取得方法は[クイックスタート](/tech/ja/api-integration/quickstart.md)を参照してください。

### 連携フロー <a href="#scenario-b-flow" id="scenario-b-flow"></a>

1. **有人対応への引き継ぎ開始を検知します**：`handoff.requested` を受信したら、自社システムで `conversation.id` を使ってチケットまたはセッションを作成し、`contact.id` を記録します。イベントに会話本文は含まれません。引き継ぎ前の会話内容が必要な場合は、`conversation.id` を使って API ドキュメントの[メッセージ一覧の取得](https://docs.maiagent.ai/api/api-reference/dui-hua-he-xun-xi#messages-list)を呼び出します。その後 `handoff.assigned` を受信した場合は、会話が MaiAgent 管理画面のメンバーに割り当てられたことを示します。`assignee.id` がそのメンバーです。
2. **訪問者のメッセージとオペレーターの返信を受信します**：各メッセージ Webhook の payload には、会話の現在の状態が含まれます。`conversation.auto_reply_enabled` が `false` のメッセージのみを処理すると、Agent が自動返信している間のトラフィックを除外できます。`sender.type` で訪問者（`contact`）、オペレーター（`user`）、Agent（`chatbot`）を区別します。フィールド定義は [Webhook › フィールドの説明](/tech/ja/serve/webhook.md#standard-fields)を参照してください。
3. **オペレーターの返信を会話に書き戻します**：API キーを使って `POST /api/v1/messages/outgoing/` を呼び出し、`conversation` と `content` を指定します。MaiAgent は訪問者が利用する会話プラットフォームにメッセージを送信します。送信者は API キーを所有するメンバーであり、そのメンバーには対象プラットフォームの会話アクセス権限が必要です。フィールドは API ドキュメントの[能動的なメッセージの送信](https://docs.maiagent.ai/api/api-reference/dui-hua-he-xun-xi#messages-outgoing-create)を参照してください。
4. **有人対応への引き継ぎを終了します**：対応終了後に `return-to-ai` を呼び出すと（呼び出し方法は[ステップ 6](#step-return)と同じです）、Agent が再び引き継ぎます。自社が API を呼び出した場合でも、メンバーが管理画面で「AI Agent に戻す」をクリックした場合でも、`handoff.returned_to_ai` を受信します。このイベントに基づいて自社システムのセッションを閉じてください。

{% hint style="warning" %}
推奨の引き受け方式＋タイムアウトなしの設定では、有人対応への引き継ぎ後も会話は待機キューに残り、`conversation.progress_status` は `waiting_for_human` になります。MaiAgent 管理画面のメンバーに会話が割り当てられた場合のみ、`human_serving` に変わります。有人対応中かどうかは `auto_reply_enabled` で判断してください。`progress_status` が `human_serving` かどうかだけを確認すると、訪問者のメッセージを取りこぼします。
{% endhint %}

### 呼び出し例 <a href="#scenario-b-examples" id="scenario-b-examples"></a>

**（1）有人対応への引き継ぎ中に受信するメッセージ Webhook**（MaiAgent 標準形式、抜粋）：`auto_reply_enabled` が `false` の場合は有人対応中です。`sender.type` が `contact` の場合は訪問者のメッセージです。

```json
{
  "id": "9d2f7a10-...",
  "type": "incoming",
  "content": "注文の配送先住所を変更したいです",
  "created_at": "2026-09-09T02:30:00+00:00",
  "conversation": {
    "id": "6c2b7c1e-...",
    "title": "...",
    "type": "individual",
    "status": "queued",
    "progress_status": "waiting_for_human",
    "auto_reply_enabled": false,
    "assignee": null
  },
  "inbox": { "id": "0f9a3d42-...", "name": "公式サイトのカスタマーサポート", "channel_type": "web" },
  "contact": { "id": "a4c1f6b3-...", "name": "王小明", "email": null, "phone_number": null },
  "sender": { "id": "a4c1f6b3-...", "name": "王小明", "type": "contact" },
  "attachments": [],
  "metadata": {}
}
```

**（2）オペレーターの返信を会話に書き戻します**：`conversation` と `content` のみを指定すれば、API キーを所有するメンバーとして、訪問者が利用する会話プラットフォームにメッセージが送信されます。

```bash
curl -X POST "https://api.maiagent.ai/api/v1/messages/outgoing/" \
  -H "Authorization: Api-Key YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversation": "6c2b7c1e-...",
    "content": "こんにちは。ご住所を東京都新宿区…に更新しました。"
  }'
```

**（3）3 つのステップをまとめた例です**（Python、`requests`）：

```python
import requests

API = "https://api.maiagent.ai/api/v1"
HEADERS = {"Authorization": "Api-Key YOUR_API_KEY"}


def on_message_webhook(payload: dict) -> None:
    conv = payload["conversation"]
    if conv["auto_reply_enabled"]:
        return  # Agent が自動返信している間のトラフィックはサポートシステムに送りません
    if payload["sender"]["type"] == "contact":
        push_to_agent_console(conv["id"], payload["content"])  # 訪問者のメッセージ→自社のオペレーター画面


def reply(conversation_id: str, text: str) -> None:
    requests.post(f"{API}/messages/outgoing/", headers=HEADERS,
                  json={"conversation": conversation_id, "content": text}, timeout=10).raise_for_status()


def finish(conversation_id: str) -> None:
    requests.patch(f"{API}/conversations/{conversation_id}/return-to-ai/", headers=HEADERS, timeout=10).raise_for_status()
```

### 注意事項 <a href="#scenario-b-notes" id="scenario-b-notes"></a>

* API で書き戻したオペレーターの返信は、Outgoing メッセージ Webhook でも一度送信されます（`sender.type` は `user` です）。自社システムで重複表示しないよう、メッセージの `id` で重複を排除してください。
* 別のメンバーに転送すると、`handoff.assigned` が再度送信され、`assignee.id` は新しい担当者になります。`conversation.id` で既存のセッションを更新し、チケットを重複作成しないでください。
* メッセージ Webhook と有人対応への引き継ぎ Webhook では検証方法が異なります。[連携前のよくある質問 › 認証](#faq-auth)を参照してください。

## イベント一覧 <a href="#events" id="events"></a>

| `event`                  | 発生するタイミング                                                                     | 自社システムにとっての意味                                |
| ------------------------ | ----------------------------------------------------------------------------- | -------------------------------------------- |
| `handoff.requested`      | AI が有人対応を必要と判断し、会話が待機キューに入り、AI の返信が停止します                                      | 自社のオペレーターが引き継ぎます                             |
| `handoff.assigned`       | 会話が MaiAgent 管理画面のオペレーターメンバーに割り当てられます（管理画面での引き受け、転送、自動割り当てが対象です。転送時は再度送信されます） | すべてのオペレーターが自社システムで対応する場合、このイベントは受信しません       |
| `handoff.returned_to_ai` | 自社が `return-to-ai` を呼び出すか、メンバーが管理画面で「AI Agent に戻す」をクリックします                    | AI の返信が再開され、チケットをクローズできます                    |
| `handoff.queue_timeout`  | 待機タイムアウトが満了し、MaiAgent が自動的に会話を AI に戻します                                       | AI の返信が再開しています。オペレーターがまだ対応中の場合は、アラートが必要な異常です |

各イベントには `GET /api/v1/conversations/{id}/events/` に対応する `event_type`（`transfer_triggered`／`human_assigned`／`returned_to_ai`／`queue_timeout`）があり、照合に使用できます。

{% hint style="info" %}
各イベントは別々のバックグラウンドタスクで送信されるため、**到着順序は保証されません**。また、再試行で重複する場合もあります。イベントの `id` で重複を排除し、`occurred_at` で順序を判断してください。`handoff.assigned` は、引き継ぎがすでに開始されたことを暗黙に示すものとして扱ってください。
{% endhint %}

### API で現在の状態を照会します <a href="#query-state" id="query-state"></a>

Webhook に加えて、現在誰が会話を処理しているかをいつでも照会できます。

```bash
GET https://api.maiagent.ai/api/v1/conversations/{conversationId}/
```

`status`（`open`／`queued`／`resolved`）、`autoReplyEnabled`、`progressStatus`（`ai_processing`／`waiting_for_human`／`human_serving`）で状態を把握できます。`GET /api/v1/conversations/{conversationId}/events/` は、有人対応への引き継ぎ関連のイベント履歴（`transfer_triggered`、`queued`、`human_assigned`、`returned_to_ai`、`queue_timeout` など）を返し、照合や補完処理に使用できます。

## 連携前のよくある質問 <a href="#kickoff-faq" id="kickoff-faq"></a>

カスタマーサポートシステムの提供会社がキックオフ時によく尋ねる質問と回答をまとめています。双方の連携ドキュメントの付録として、そのまま利用できます。

### 環境とパス <a href="#faq-environments" id="faq-environments"></a>

| 環境  | Base URL                              |
| --- | ------------------------------------- |
| テスト | `https://api-dev.maiagent.ai/api/v1/` |
| 本番  | `https://api.maiagent.ai/api/v1/`     |

この連携で使用するパスは固定です。`POST /web-chats/{webChatId}/setup-contact-credentials/`、`POST /conversations/`、`POST /messages/`、`PATCH /conversations/{id}/return-to-ai/` を使用し、照合には `GET /conversations/{id}/` と `GET /conversations/{id}/events/` を使用します。テスト環境の組織、API キー、Web Chat は、連携窓口が作成して提供します。

### 認証 <a href="#faq-auth" id="faq-auth"></a>

* **お客様が MaiAgent を呼び出す場合**：ヘッダー `Authorization: Api-Key <キー>`。ID 同期 API にはキーは不要で、`webChatId` で識別します。
* **MaiAgent がお客様へ送信する場合**：どちらも HMAC-SHA256 で署名し、ヘッダーは同じ `X-MaiAgent-Signature-256: sha256=<hex>` ですが、署名対象が異なります。メッセージ Webhook（Secret Token の設定が必要）は「`X-MaiAgent-Timestamp` の値 + `.` + 元のリクエストボディ」に署名します。詳しくは [Webhook › 署名とタイムスタンプの検証](/tech/ja/serve/webhook.md#webhook-signature) を参照してください。有人対応への引き継ぎ Webhook は、元のリクエストボディのみに署名します。

### タイムアウト、リトライ、レート制限 <a href="#faq-limits" id="faq-limits"></a>

| 方向                                 | タイムアウト                                    | リトライ                                                                                                                                                                                        |
| ---------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| お客様が `POST /messages/` を呼び出す       | 同期的に 201 を返します。クライアント側のタイムアウトは 10 秒を推奨します | 4xx の場合はまずリクエストを修正してください。5xx またはタイムアウトの場合は結果が不確定のため、まず照合を行い、そのまま再送しないでください                                                                                                                  |
| メッセージ Webhook（MaiAgent → お客様）      | 30 秒                                      | タイムアウト、接続失敗、5xx、429 の場合、約 1 分後、5 分後、15 分後にそれぞれ 1 回ずつ、最大 3 回再送します。その他の 4xx は再送しません。2xx を返す前にデータを保存し、メッセージの `id` で重複排除してください。詳しくは [Webhook › 自動再送](/tech/ja/serve/webhook.md#retry) を参照してください |
| 有人対応への引き継ぎ Webhook（MaiAgent → お客様） | 10 秒                                      | 失敗した場合は 60 秒ごとに最大 3 回リトライします。イベントの `id` で重複排除してください                                                                                                                                         |

`POST /messages/` は冪等性を保証しません。サーバー側ではすでにメッセージが作成されていても、レスポンスが通信途中で失われる場合があります。まず会話履歴とお客様側の送信記録で結果を確認してください。確認できないままそのまま再送すると、メッセージが重複して作成され、AI の返信が再度トリガーされる可能性があります。

API キーごとに 1 分あたりのリクエスト上限（RPM）を設定できます。デフォルトでは無制限です。本番稼働前に想定トラフィックをお知らせいただき、連携窓口が設定します。

### 送信元 IP のホワイトリスト <a href="#faq-egress" id="faq-egress"></a>

MaiAgent が Webhook を送信する際の送信元 IP は固定です。受信側でホワイトリストが必要な場合は、連携窓口に本番環境とテスト環境の最新の一覧をご請求ください。MaiAgent は、お客様の受信側ドメインに対する送信先制限は設けていません。

### 会話セッションの対応 <a href="#faq-session" id="faq-session"></a>

キーはコンタクトの `sourceId` です（チャネル間での ID 衝突を避けるため、`{プラットフォーム}:{お客様のユーザー ID}` の形式を推奨します）。同じ `sourceId` で ID 同期 API を繰り返し呼び出しても、同じ `contactId` が返されます。会話の作成後は**存続期間の制限がない**ため、同じ会話 ID を長期間使い続けてコンテキストを維持できます。また、クローズ後に同じコンタクトに対して新しい会話を作成し、最初からやり直すこともできます。

### 有人対応への引き継ぎの判定ロジック <a href="#faq-handoff-logic" id="faq-handoff-logic"></a>

判定モデルが会話の直近 N 件のメッセージに基づいて判断します。デフォルトのルールは、訪問者が明確に有人対応を求めた場合、AI が対応できる範囲を超える質問の場合、訪問者の感情が良くない場合、人による確認が必要な課金・請求関連の操作が含まれる場合です。ルールは<mark style="color:blue;">ロール指示</mark>で自然言語により調整でき、キーワードや、確信度が低い場合は引き継ぐといった条件を追加できます。<mark style="color:blue;">サービス時間</mark>を設定して、時間外に引き継ぐかどうかを決めることもできます。判定結果が `handoff.requested` イベントです。

### 複数回の返信とメッセージ形式 <a href="#faq-message-format" id="faq-message-format"></a>

AI の返信 1 件ごとにメッセージ Webhook を 1 回送信します（1 件につき 1 リクエスト）。バッチ送信は行いません。1 件の返信に複数の添付ファイルを含めることができます。お客様のシステムが配列形式を要求する場合は、カスタムテンプレートで要素 1 つの配列を出力してください。標準ではテキスト（Markdown）と添付ファイル（画像／動画／音声／ファイル）に対応しています。ボタン、カード、クイックリプライなどのチャネル固有の形式は標準の対象外のため、キックオフ時にご要望をお知らせください。別途検討します。

### 添付ファイルの URL と有効期間 <a href="#faq-attachments" id="faq-attachments"></a>

AI の返信に含まれる添付ファイルは、カスタムテンプレートで `attachment.file.url` として出力されます。これは署名付き URL で、**有効期間は 1 時間**です。受信後すぐにファイルを取得して保存してください。訪問者がアップロードした添付ファイルについては、お客様のシステム側でダウンロード可能な URL を先に取得し、メッセージ送信時に `attachments[]` に指定してください。

### エラーと利用状況の照会 <a href="#faq-observability" id="faq-observability"></a>

メッセージ Webhook の送信ごとのリクエスト、レスポンス、ステータスコードは、MaiAgent 管理画面の Agent ページにある <mark style="color:blue;">Webhook</mark> タブで確認できます。会話の状態と有人対応への引き継ぎイベントは、会話 API とイベント履歴 API で照会して照合できます。AI の利用状況は、管理画面の<mark style="color:blue;">利用統計</mark>で確認できます。有人対応への引き継ぎ Webhook の送信に失敗した場合は、MaiAgent の監視アラートに記録されます。

## 連携チェックリスト <a href="#checklist" id="checklist"></a>

* [ ] 管理画面：Outgoing Webhook が設定され、AI の返信を受信できる
* [ ] 管理画面：有人対応への引き継ぎが有効になっている。外部の有人オペレーターの割り当てモードが<mark style="color:blue;">引き受け制</mark>で、<mark style="color:blue;">タイムアウトなし</mark>にチェックが入っている
* [ ] 管理画面：有人対応への引き継ぎ Webhook が有効で、HTTPS エンドポイントに到達でき、署名検証に成功する
* [ ] お客様のシステム：`sourceId ↔ contactId ↔ conversationId` の対応が保存されている
* [ ] お客様のシステム：`handoff.requested` → 案件作成と引き継ぎ案内、`handoff.returned_to_ai` → 案件クローズ、`handoff.queue_timeout` → アラートまたは案件クローズ
* [ ] お客様のシステム：有人対応の終了時に `return-to-ai` を呼び出す
* [ ] 2 つの Webhook エンドポイントがどちらも冪等である：有人対応への引き継ぎイベントとメッセージ送信は、それぞれの `id` を使用する
* [ ] シナリオ B：メッセージ Webhook に Incoming と Outgoing の 2 方向が追加され、`auto_reply_enabled` で有人が対応中かどうかを判断している
* [ ] ネットワークで送信元 IP のホワイトリストが必要な場合は、連携窓口に MaiAgent の送信元 IP をご請求ください

## 関連ページ <a href="#related" id="related"></a>

* [有人対応への引き継ぎ Webhook イベント](https://docs.maiagent.ai/api/preparation/handoff-webhook)（API ドキュメント）：イベントの詳細仕様、署名検証、そのまま起動できる受信側のサンプル
* [カスタマーサポートの有人対応への引き継ぎ設定](https://docs.maiagent.ai/build/conversation-settings/human-handoff)（ユーザーマニュアル）：引き継ぎ条件、サービス時間、割り当て設定など、管理画面の項目の操作説明
* [Webhook](/tech/ja/serve/webhook.md)：メッセージ送信の形式、カスタムテンプレート、API による Webhook の管理
* [Genesys Cloud 連携](/tech/ja/serve/customer-service-system-integration/genesys-cloud-integration.md)：Genesys Cloud Open Messaging による連携。メッセージ形式、OAuth、署名検証を標準で備えています
* [会話とメッセージの作成](/tech/ja/api-integration/conversations-and-messages.md)：会話の作成とメッセージ送信のフロー。項目は API ドキュメントにリンクしています
* [コンタクト ID の同期とトークンの更新](/tech/ja/serve/contacts/contact-credentials-sync.md)：`setup-contact-credentials` の詳細仕様
* [Presigned ファイルアップロードモード](/tech/ja/api-integration/api_knowledge.md)：添付ファイルのアップロード


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.maiagent.ai/tech/ja/serve/customer-service-system-integration.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
