> 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/line-flex-message.md).

# LINE Flex Message 仕様

MaiAgent が LINE Flex Message カードを送信する仕組み：FlexMessage ツールのテンプレートと AI フィールドの形式、検証エンドポイント、応答ストリームに含まれる flex 項目、LINE への送信時の制限と失敗時の処理。

このページは、Agent に LINE Flex Message カードを返信させたいエンジニア向けです。カードのテンプレートの保存方法、Agent によるフィールドの入力方法、プラットフォームから LINE へのカードの送信方法、そして API レスポンス内でのカードの形式を説明します。

管理画面での操作（カードの追加場所、組み込みテンプレートの適用、Agent へのバインド）については、ユーザーマニュアルの [Agent UI](https://docs.maiagent.ai/build/tools/agent-ui) をご覧ください。LINE チャネルの連携手順は [チャットプラットフォームとの連携：LINE](https://docs.maiagent.ai/build/choose-channel/line) をご覧ください。このページでは操作手順を繰り返しません。

## 仕組み <a href="#how-it-works" id="how-it-works"></a>

MaiAgent が Flex カードを送信する入口は **FlexMessage ツール**（ツールタイプ `flex`。管理画面では Agent UI の FlexMessage と呼ばれます）です。1 枚のカード＝1 つのツールです。

1. あらかじめ LINE ネイティブの Flex JSON テンプレート（`flexTemplateJson`）を保存し、そのうち AI が入力するフィールド（`flexSchema`）を指定します。
2. ツールを Agent にバインドすると、`flexSchema` の各フィールドがこのツールの文字列パラメータになり、Agent は記述されたフィールドのヒントに従って入力内容を決定します。
3. Agent がツールを呼び出すと、プラットフォームがパラメータの値をテンプレートのコピーに代入して完全な Flex JSON を生成し、`flex` コンテンツ項目としてこの返信に含めます。
4. 返信が LINE に送られるとき、プラットフォームは `flex` 項目を LINE の Flex Message に変換します。Web Chat ではカードがそのままレンダリングされ、API の呼び出し元は `contentPayload.items` で同じ JSON を受け取ります。

```mermaid
sequenceDiagram
    participant U as ユーザー
    participant A as Agent
    participant P as MaiAgent プラットフォーム
    participant L as LINE

    U->>A: 「注文はどこまで届いていますか？」
    A->>A: 先に返信テキストを書き、次にカードツールを呼び出してフィールドを入力
    A->>P: tool call（AI フィールドごとに 1 つの文字列パラメータ）
    P->>P: テンプレートに代入 → 完全な Flex JSON（flex コンテンツ項目）
    P->>L: テキストメッセージ＋Flex Message（同一の返信）
    L-->>U: テキストとカード
```

カードツールの呼び出しでそのターンは終了します。ツールの出力はモデルに戻されて書き直されることはないため、返信テキストはカードを呼び出す**前**に書いておく必要があります。

{% hint style="info" %}
カードは表示専用です。注文や在庫などのリアルタイムデータを表示するには、データを取得できるツール（例：[API ツール](/tech/ja/api-integration/api-tool-engineering-guide.md)）を別途設定してください。Agent が先にデータを取得し、その値をカードのフィールドに入力します。
{% endhint %}

## テンプレートと AI フィールド <a href="#template-and-fields" id="template-and-fields"></a>

### テンプレート `flexTemplateJson` <a href="#template" id="template"></a>

* 保存するのは LINE Flex Message の `contents` です。つまり `bubble` または `carousel` コンテナであり、`type: "flex"` や `altText` を含む外側のメッセージオブジェクトではありません。プラットフォームは LINE 公式 SDK の `FlexContainer` で解析します。
* JSON オブジェクトである必要があります。FlexMessage ツールはテンプレートなしでは作成できません。
* ネストされた key はそのまま保存されます。API のフィールド名は常に camelCase ですが、`flexTemplateJson` と `flexSchema` の内部の key（例：`backgroundColor`、`paddingAll`）は変換されないため、LINE の仕様どおりに記述してください。

### AI フィールド `flexSchema` <a href="#ai-fields" id="ai-fields"></a>

`flexSchema` は JSON オブジェクトで、key はテンプレート内のフィールドのパス、value は AI へのフィールドのヒントです。

| 記述                                                            | 説明                                                                             |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `"body.contents[0].text": "注文番号"`                             | value が文字列：そのままフィールドのヒントになります                                                  |
| `"body.contents[0].text": {"prompt": "注文番号", "tag": "title"}` | value がオブジェクト：`prompt` がフィールドのヒントで、`tag` は `[title]` というプレフィックスとしてヒントの前に付加されます |

ルール：

* **パスの構文**：`.` で階層を区切り、`[インデックス]` で配列の要素を指定します。例：`body.contents[0].text`、`footer.contents[0].action.uri`。
* **パラメータ名**：パス中の英数字とアンダースコア以外の文字は `_` に置き換えられ、連続する `_` は 1 つにまとめられます。例：`body.contents[0].text` はパラメータ `body_contents_0_text` になります。名前が重複する場合は、順に `_2`、`_3` が付きます。
* **型**：すべての AI フィールドは文字列パラメータで、デフォルトは空文字列です。数値や真偽値のフィールドは AI に入力させないでください。
* **空の値はデフォルトを維持**：Agent が入力しなかったフィールドや空文字列を入力したフィールドは、テンプレート内の元の値が保持されます。
* **パスが見つからない場合はスキップ**：テンプレートを変更してパスが存在しなくなった場合、そのフィールドは書き込まれず、エラーも発生しません。テンプレートを変更したら、`flexSchema` も併せて確認してください。

例：タイトルと照会リンクを AI が入力し、それ以外は固定の注文ステータスカード。

```json
{
  "flexTemplateJson": {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        { "type": "text", "text": "注文 A000", "weight": "bold", "size": "lg" },
        { "type": "text", "text": "下のボタンから配送状況をご確認ください", "size": "sm", "wrap": true }
      ]
    },
    "footer": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        {
          "type": "button",
          "style": "primary",
          "action": { "type": "uri", "label": "状況を確認", "uri": "https://example.com/orders" }
        }
      ]
    }
  },
  "flexSchema": {
    "body.contents[0].text": { "prompt": "「注文 」に注文番号を続けたもの", "tag": "title" },
    "footer.contents[0].action.uri": "該当の注文の照会ページの完全な URL（https で始まるもの）"
  }
}
```

モデルには `body_contents_0_text` と `footer_contents_0_action_uri` の 2 つのパラメータが見えます。

## API でカードを作成・検証する <a href="#api" id="api"></a>

### 作成と管理 <a href="#create-and-manage" id="create-and-manage"></a>

FlexMessage ツールは Agent UI 専用のエンドポイント `/api/v1/agent-ui-tools/`（一覧、作成、更新、削除）を使用します。一般のツール用エンドポイントでは作成できません（`403` が返ります）。呼び出し元には Agent UI ページへのアクセス権限が必要です。

| フィールド                  | 説明                                                                              |
| ---------------------- | ------------------------------------------------------------------------------- |
| `toolType`             | `flex`。このエンドポイントでは省略時のデフォルトが `flex` です                                          |
| `name`                 | モデルが呼び出すときのツール名。同一組織内で重複できません。`snake_case` を推奨します                               |
| `displayName`          | 管理画面での表示名                                                                       |
| `description`／`prompt` | 少なくとも 1 つは入力します。`prompt` がモデルへのツールの説明として優先されるため、このカードを送るべき**タイミング**を明確に記述してください |
| `flexTemplateJson`     | テンプレート。[前のセクション](#template)を参照してください                                            |
| `flexSchema`           | AI フィールド（任意）                                                                    |

保存時に、プラットフォームは LINE SDK でテンプレートの構造チェックを行います（LINE には接続しません）。チェックに通らない場合は `400` が返り、`detail` は「Invalid FlexMessage template: …」とエラーの原因です（フィールドが不足している場合はフィールド名が列挙されます）。テンプレートの内容が保存済みのものと異なる場合にのみ再チェックされるため、名前やグループだけを変更する場合に古いテンプレートで拒否されることはありません。

ツールを作成したら、他のツールと同様に Agent にバインド（Agent の `tools` フィールド）して初めて有効になります。Agent は Agent モードを使用している必要があります。ユーザーマニュアルの [Agent にバインドする](https://docs.maiagent.ai/build/tools/agent-ui#bind-to-chatbot)をご覧ください。フィールドの詳細は [API ドキュメント](https://docs.maiagent.ai/api)をご覧ください。

### LINE 公式による検証 <a href="#validate" id="validate"></a>

保存時の構造チェックは、LINE SDK がテンプレートを解析できるかどうか（フィールドの不足や SDK が解析できないフィールド）しか確認せず、LINE が受け付けないかどうか（例：URL の形式、フィールド値の範囲外）は判断できません。本番公開の前に検証エンドポイントを使用してください。

```http
POST /api/v1/agent-ui-tools/validate-flex/
Authorization: Api-Key <API キー>
Content-Type: application/json

{ "flexTemplateJson": { "type": "bubble", "body": { … } } }
```

レスポンス：

```json
{
  "isValid": false,
  "details": [{ "property": "/footer/contents/0/action/uri", "message": "invalid uri" }],
  "source": "line",
  "tokenSource": "platform"
}
```

| フィールド         | 説明                                                                                                                                                                               |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isValid`     | 検証に通ったかどうか                                                                                                                                                                       |
| `details`     | フィールドごとのエラー。`property` はエラー箇所の JSON パスで、形式は LINE のエラーレスポンスに準じます                                                                                                                  |
| `source`      | `line`：LINE 公式の検証エンドポイントによる判定。`local`：LINE には送信されていません。テンプレートが構造チェックに通らなかった場合（この場合 `isValid` は `false` で、token があっても LINE には送信されません）、または利用可能な LINE token がなく構造チェックのみを行った場合が該当します |
| `tokenSource` | LINE の呼び出しに使用した token：`platform`（プラットフォーム提供）または `org_channel`（組織の LINE チャネルの token）。`source` が `local` の場合は `null` です                                                            |

動作の詳細：

* 呼び出すのは LINE の `validate_push` です。検証のみを行い、メッセージは送信されず、プッシュ配信の上限も消費しません。
* テンプレートは、構造チェックに通って初めて LINE に送信されます。
* まずプラットフォーム提供の検証用 token を使用します。token がない、または LINE に拒否された（`401`）場合は、組織で連携済みの LINE チャネルの token を順に使用します。どれもない（またはすべて拒否された）場合は `source: "local"` を返します。
* LINE への 1 回の呼び出しのタイムアウトは 10 秒です。LINE のタイムアウト、`5xx`、またはネットワークエラーの場合は `503` を返します。より弱いローカルチェックに黙ってフォールバックすることはないため、しばらくしてから再試行してください。
* 同一 JSON に対する LINE の判定結果は 10 分間キャッシュされます。
* 1 ユーザーあたり 1 分間に最大 30 回で、超過すると `429` を返します。API キー自体の 1 分あたりの上限も同時に適用されます。

## 返信内の `flex` コンテンツ項目 <a href="#content-item" id="content-item"></a>

API で返信を受け取る場合（ストリーミングまたは同期。[会話とメッセージの応答](/tech/ja/api-integration/dui-hua-yu-xun-xi-hui-fu-chuan-liu-tong-bu.md)を参照）、カードは `contentPayload.items` に含まれます。

```json
{
  "type": "flex",
  "flexMessage": { "type": "bubble", "body": { … } },
  "isStreaming": false,
  "startTimestamp": "2026-10-12T10:00:00+08:00"
}
```

* `flexMessage` は AI フィールドの値が代入済みの完全なコンテナ（`bubble` または `carousel`）で、そのまま LINE SDK や独自のカードレンダラーに渡せます。
* `isStreaming: false` で `flexMessage` を持つ項目のみを処理してください。`isStreaming: true` の項目は `delta`（JSON テキストの断片）のみを持つため、完成した項目が現れてからレンダリングしてください。
* 1 つの返信に複数のカードを含めることができます。`items` の順に表示します。
* `contentPayload.content`（各項目のプレーンテキストをまとめたもの）では、カードは JSON 文字列として現れます。テキストだけを表示したい場合は、`type: "text"` の項目を使用してください。

## LINE への送信ルール <a href="#line-delivery" id="line-delivery"></a>

プラットフォームは、返信の `contentPayload.items` を順に LINE のメッセージオブジェクトに変換します。テキスト項目はテキストメッセージに、`flex` 項目は Flex Message になり、同一の返信として送信されます。

| 項目          | ルール                                                                         |
| ----------- | --------------------------------------------------------------------------- |
| メッセージ数      | 1 回につき最大 5 件（LINE の上限）。超過分は送信されません                                          |
| テキストの長さ     | 1 件のテキストが 5,000 文字を超える場合は複数のメッセージに分割され、5 件の上限に含まれます                         |
| `altText`   | この返信のすべてのテキスト項目を連結した先頭 400 文字。返信にテキストがない場合は「View details」（ロケールに応じて翻訳）を使用します |
| クイックリプライボタン | 最後のメッセージに付与されます                                                             |
| グループでの引用    | グループ会話での引用はテキストメッセージにのみ付与され、Flex Message には引用が付きません                         |

`altText` は LINE の通知やトーク一覧のプレビューに表示されます。プレビューに内容が表示されるよう、Agent にカードの前に一言説明を書かせてください。

### Agent がテキストを書かずにカードだけを送る場合 <a href="#text-with-cards" id="text-with-cards"></a>

モデルによっては、テキストを一切書かずにカードツールを直接呼び出すことがあり、ユーザーには説明のないカードだけが表示されます。Agent の設定 `requireTextWithFlexCards` を `true` にしている場合、そのターンがカードのみ（またはカードとクイックリプライボタンのみ）でテキストがまったくないと、プラットフォームはプロンプトを付加してモデルに再度返信を求め、テキストを先に書いてからカードを送るよう要求します。

* 再試行は 1 ターンにつき最大 1 回です。モデルが依然としてカードだけを送った場合でも、再試行の結果が使用されます。
* 再試行は別途課金されるモデル呼び出しです。
* デフォルトではオフです。メニューカード 1 枚だけを返す設計の Agent もあるためです。

### その他のチャネル <a href="#other-channels" id="other-channels"></a>

`flex` 項目をカードとしてレンダリングするのは Web Chat と LINE だけです。その他のチャネル（例：Messenger、Instagram）には対応する変換がありません。Agent Teams でサブ Agent が送信したカードはこれらのチャネルでは送信されず、代わりにカードの可視テキストが上位の Agent に渡されて言い換えられます。複数のチャネルで使用する Agent では、カードを返信の唯一の内容にしないでください。

## 失敗とエラー処理 <a href="#errors" id="errors"></a>

| 状況                                     | プラットフォームの動作                                                                              | 推奨事項                                                                   |
| -------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| 作成または更新時にテンプレートの構造が不正                  | `400`。`detail` にエラーの原因が示されます                                                             | テンプレートを修正して再送信してください                                                   |
| 検証時に LINE に接続できない                      | `503`                                                                                    | しばらくしてから再試行してください                                                      |
| 送信前に SDK がカードを解析できない                   | そのカードはスキップされ（エラーを記録）、残りのメッセージは送信されます。返信全体に送信可能なメッセージが 1 件もない場合は、そのメッセージのテキスト内容を代わりに送信します | 本番公開前に[検証エンドポイント](#validate)でテンプレートを確認してください                           |
| LINE がこの返信を拒否（`400`。例：AI が不正な URL を入力） | 同じメッセージ群をプッシュ配信で再送します。LINE が再度 `4xx` で拒否した場合は再試行せず、この返信（同じメッセージ群のテキストを含む）は届きません          | AI には誤りが起きにくいフィールドのみを入力させてください。URL 系のフィールドは形式を明確に記述するか、テンプレートで固定してください |

{% hint style="warning" %}
検証エンドポイントが検証するのはテンプレート自体のみです。AI が入力する値は会話の時点で代入されるため、たとえば AI が不正な URL を入力すると、LINE がメッセージ群全体を拒否する可能性があります。形式の要件が厳しいフィールド（`uri`、色、サイズ）は、AI に入力させずテンプレートで固定することをお勧めします。
{% endhint %}

## 会話メモリ内のカード <a href="#memory" id="memory"></a>

カードの送信後、そのターンの会話メモリに書き込まれるのは JSON 全体ではなく、カード上で見えるテキスト（`text`、`span`、ボタンの `label`、`altText`）です。LINE の表示順（header → hero → body → footer）に並べられ、長さの上限があります。以降の会話では、Agent はカード上の内容を参照できますが、ボタンの URL など表示されないフィールドは読み取れません。

## 本番公開前のチェックリスト <a href="#checklist" id="checklist"></a>

* [ ] テンプレートが `bubble` または `carousel` コンテナであり、[検証エンドポイント](#validate)に通っている（`source` が `line`）。
* [ ] `flexSchema` で AI に開放しているのはテキスト系のフィールドのみである。テンプレートを変更した後は、パスが引き続き見つかることを確認した。
* [ ] ツールの `prompt` に使用するタイミングを明記し、テキストを先に書いてからカードを送るよう求めている。必要に応じて `requireTextWithFlexCards` を有効にした。
* [ ] 1 つの返信のテキストとカードの合計が 5 メッセージを超えない。
* [ ] LINE の実機でテストした：カードの表示、ボタンの動作、通知プレビューのテキスト。


---

# 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/line-flex-message.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.
