@super_studio/ecforce-ai-agent-react
v1.5.0
Published
このドキュメントでは、`@super_studio/ecforce-ai-agent-react` と `@super_studio/ecforce-ai-agent-server` を使って、Webアプリに AI Agent のチャット UI とサーバー連携を組み込む手順を説明します。
Keywords
Readme
セットアップ
このドキュメントでは、@super_studio/ecforce-ai-agent-react と @super_studio/ecforce-ai-agent-server を使って、Webアプリに AI Agent のチャット UI とサーバー連携を組み込む手順を説明します。
想定構成は以下です。
- フロントエンドで
@super_studio/ecforce-ai-agent-reactを使ってチャット UI を表示する - バックエンドで
@super_studio/ecforce-ai-agent-serverを使ってセッショントークンを発行する - 必要に応じて MCP エンドポイントでトークンを検証し、アプリ固有のツールを公開する
1. インストール
pnpm add @super_studio/ecforce-ai-agent-react @super_studio/ecforce-ai-agent-server2. 環境変数を設定する
通常の本番環境 (https://agent.ec-force.com) に接続するだけであれば、NEXT_PUBLIC_CHATBOT_URL は不要です。
@super_studio/ecforce-ai-agent-server を使う場合は、API キーとして AI_AGENT_API_KEY を設定してください。
MCP を実装する場合は、あわせて MCP_TOKEN_SECRET も必要です。
AI_AGENT_API_KEY と MCP_TOKEN_SECRET は AI チームから共有された値を使用してください。
AI_AGENT_API_KEY=your-api-key
MCP_TOKEN_SECRET=your-mcp-token-secret開発環境やプレビュー環境など、本番以外の AI Agent に接続したい場合のみ、接続先 URL を設定します。
開発用のエンドポイントは以下です。
NEXT_PUBLIC_CHATBOT_URL=https://dev-agent.ec-force.com
AI_AGENT_API_ENDPOINT=https://dev-agent.ec-force.comNEXT_PUBLIC_CHATBOT_URL: フロントエンドのChatbotSheet/ChatbotFrameを dev / preview 環境へ向けたい場合に使いますAI_AGENT_API_ENDPOINT: サーバー側のcreateClient()を dev / preview 環境へ向けたい場合に使いますAI_AGENT_API_KEY: サーバー SDK から API を呼ぶために必須ですMCP_TOKEN_SECRET: MCP トークンの署名・検証に使います。MCP を実装する場合に必須です
3. @super_studio/ecforce-ai-agent-react のセットアップ
3-1. スタイルを読み込む
グローバル CSS で、パッケージが提供するスタイルを読み込みます。
@import "@super_studio/ecforce-ai-agent-react/preset.css";
@import "@super_studio/ecforce-ai-agent-react/chatbot-sheet.css";3-2. アプリを ChatbotProvider でラップする
チャット UI や useChatbot() を使う場合は、アプリ全体または必要な範囲を ChatbotProvider で囲みます。
"use client";
import { ChatbotProvider } from "@super_studio/ecforce-ai-agent-react";
type Props = {
children: React.ReactNode;
};
export function AppProviders({ children }: Props) {
return <ChatbotProvider>{children}</ChatbotProvider>;
}3-3. チャット UI を表示する
ChatbotSheet にアプリ名、セッション取得関数を渡します。通常は本番環境へ接続されるため、URL 指定は不要です。
"use client";
import { ChatbotSheet } from "@super_studio/ecforce-ai-agent-react";
export function Chatbot() {
return (
<ChatbotSheet
appName="your-app-name"
getSession={async () => {
const res = await fetch("/api/agent/session", {
method: "POST",
});
if (!res.ok) {
throw new Error("Failed to create AI agent session");
}
return (await res.json()) as {
token: string;
expiresAt: string;
};
}}
/>
);
}各 props の役割
url: AI Agent サーバーのベース URL。dev / preview 環境に向けたい場合のみ指定しますappName: 呼び出し元アプリを識別する名前getSession: AI Agent に接続するためのセッショントークンを返す関数
dev / preview 環境へ接続する場合のみ、以下のように url を指定してください。
<ChatbotSheet
url={process.env.NEXT_PUBLIC_CHATBOT_URL}
appName="your-app-name"
getSession={...}
/>3-4. アプリ側の状態や文脈を AI Agent に渡す
useChatbot() の sendAppMessage() を使うと、ホストアプリから AI Agent に対してプログラム経由でメッセージを送れます。
典型的には、以下のような場面で使います。
- 現在表示中の商品、注文、顧客などを前提に AI へ依頼したい
- ユーザーが押したボタンに応じて、定型プロンプトをそのまま送信したい
- 画面には見せたくない補足情報を AI にだけ渡したい
- 画像やファイル URL を添付して、その内容を前提に会話を始めたい
sendAppMessage() を呼ぶと、チャットが閉じていても自動で開きます。チャット iframe の初期化がまだ終わっていない場合でも、メッセージは内部で一時保持され、準備完了後に送信されます。
"use client";
import { useChatbot } from "@super_studio/ecforce-ai-agent-react";
export function SendContextButton() {
const { sendAppMessage } = useChatbot();
return (
<button
onClick={() => {
sendAppMessage({
title: "売上ダッシュボードの要約",
message:
"現在の売上ダッシュボードを前提に、注目すべき変化を3つ挙げてください。",
hiddenMessage:
"dashboardId=dashboard_123, dashboardName=売上ダッシュボード",
});
}}
>
コンテキストを送信
</button>
);
}sendAppMessage() の payload
type SendAppMessagePayload = {
title?: string;
message: string;
hiddenMessage?: string;
startOnNewChat?: boolean;
model?: string;
attachments?: {
fileName: string;
mediaType: string;
url: string;
}[];
};message: AI Agent に実際に依頼したい本文です。必須ですtitle: 依頼の要約タイトルです。UI 上でタスク名のように扱いたいときに使いますhiddenMessage: ユーザーに見せなくてよい補足文脈です。内部 ID、画面状態、回答方針などを渡す用途に向いていますstartOnNewChat:trueなら新しいチャットを開始して送信します。省略時はtrueです。現在の会話の続きに送りたい場合だけfalseを指定しますmodel: このメッセージ送信で使うモデルの alias key です。例:claude-sonnet-4-6attachments: AI Agent に参照させたい添付ファイルです。公開 URL で取得できるファイルを渡してください
visible な依頼と hidden な文脈の使い分け
基本的には、ユーザーが見ても自然な内容を message に書き、アプリ内部の補足情報を hiddenMessage に分けるのがおすすめです。
message: 「この注文の要点を要約して」hiddenMessage:orderId=ord_123,status=paid,customerTier=gold
このように分けると、ユーザー向けの依頼文を保ちながら、AI 側には必要な文脈も渡せます。
新しいチャットで送るか、現在の会話に続けるか
新しい依頼を独立した会話として扱いたい場合は、デフォルトのまま startOnNewChat: true を使います。すでに進行中の会話に追加指示したい場合は false を指定します。
sendAppMessage({
title: "続きの依頼",
message: "最も良い案を、2行のヒーローコピーに言い換えてください。",
startOnNewChat: false,
});添付ファイルを渡す例
sendAppMessage({
title: "バナー案のレビュー",
message: "添付画像を確認し、改善案を3つ提案してください。",
attachments: [
{
fileName: "campaign-banner.png",
mediaType: "image/png",
url: "https://example.com/campaign-banner.png",
},
],
});これにより、AI Agent 側で現在の画面や対象データに応じた応答をしやすくなります。
送信せず、入力欄に入れるだけにしたい場合は setInput()
sendAppMessage() はそのまま送信されます。ユーザーに内容を確認・編集してもらってから送信させたい場合は、useChatbot() の setInput() を使います。
"use client";
import { useChatbot } from "@super_studio/ecforce-ai-agent-react";
export function SalesReportButton() {
const { setInput } = useChatbot();
return (
<button
type="button"
onClick={() =>
setInput("直近1週間の売上分析を行い、キャンバス上のレポートにまとめてください")
}
>
売上レポートを作る
</button>
);
}sendAppMessage() と同じく、チャットが閉じていても自動で開き、iframe の初期化が終わっていない場合はテキストを一時保持して準備完了後に反映します。送信はユーザーが送信ボタンを押すまで行われません。
| | sendAppMessage() | setInput() |
|---|---|---|
| 送信 | する | しない(入力欄に入れるだけ) |
| チャットを自動で開く | する | する |
| 初期化前の呼び出し | 保持して後で送る | 保持して後で反映する |
| hidden な文脈・添付 | 渡せる | 渡せない(テキストのみ) |
3-5. useClientTool() でクライアントツールを登録する
ブラウザ上で実行したい処理を AI Agent から呼ばせたい場合は、useClientTool() を使います。
典型的には、以下のような用途で使います。
- 現在開いている画面の React state を参照して結果を返す
- ユーザー確認付きでクライアント側の state を更新する
- クライアント側の UI 操作をトリガーする
useClientTool() は ChatbotProvider 配下で呼び出してください。引数定義には zod を使います。
"use client";
import { useState } from "react";
import { z } from "zod";
import { useClientTool } from "@super_studio/ecforce-ai-agent-react";
export function CartToolRegistration() {
const [selectedSku, setSelectedSku] = useState("sku_001");
const [isPinned, setIsPinned] = useState(false);
useClientTool({
name: "checkSelectedSku",
displayName: "選択中SKU確認",
description: "現在画面で選択中の商品 SKU を返します。",
summary: "選択中の SKU を返します。",
parameters: z.object({}),
execute: () => {
return {
selectedSku,
isPinned,
};
},
});
useClientTool({
name: "togglePinnedState",
displayName: "ピン留め切り替え",
description: "現在の商品をピン留めするかどうかを切り替えます。",
summary: "ピン留め状態を更新します。",
requireConfirmation: true,
parameters: z.object({
pinned: z.boolean().describe("更新後のピン留め状態"),
}),
execute: ({ pinned }) => {
setIsPinned(pinned);
return {
selectedSku,
isPinned: pinned,
};
},
});
return (
<div>
<p>selectedSku: {selectedSku}</p>
<p>isPinned: {String(isPinned)}</p>
<button onClick={() => setSelectedSku("sku_002")}>
SKU を切り替える
</button>
</div>
);
}useClientTool() の options
type UseClientToolOptions<TParameters extends z.ZodTypeAny> = {
name: string;
displayName: string;
description: string;
summary?: string;
requireConfirmation?: boolean;
parameters: TParameters;
execute: (args: z.output<TParameters>) => Promise<unknown> | unknown;
};name: ツール識別子です。内部では自動でpage_プレフィックスが付きますdisplayName: UI 上で表示するツール名ですdescription: AI Agent が参照する詳細説明です。何をするツールか、どんな引数を受けるかを明確に書いてくださいsummary: ユーザー向けの短い要約ですrequireConfirmation:trueの場合、実行前にユーザー確認を要求しますparameters: ツール引数を表すzodスキーマですexecute: 検証済み引数を受け取ってクライアント側の処理を実行する関数です
補足
nameにpage_を自分で付けても動きますが、通常は素の名前で問題ありませんexecuteの返り値は AI Agent に渡されるため、JSON 化しやすい値を返すのがおすすめです- コンポーネントがアンマウントされるとツール登録は自動で解除されます
4. @super_studio/ecforce-ai-agent-server のセットアップ
4-1. サーバー側で AI Agent セッションを発行する
フロントエンドの getSession() から呼ばれる API を用意し、createClient() を使って AI Agent サーバーへセッション作成を依頼します。
このとき、サーバー環境に AI_AGENT_API_KEY の設定が必要です。
以下は Next.js App Router の Route Handler 例です。
import { NextResponse } from "next/server";
import { createClient } from "@super_studio/ecforce-ai-agent-server";
const aiClient = createClient();
export async function POST() {
// ここは自分の認証基盤に置き換えてください
const currentUser = {
email: "[email protected]",
projectId: "project_123",
};
const session = await aiClient.internalChat.createSession({
email: currentUser.email,
projectId: currentUser.projectId,
});
return NextResponse.json(session);
}dev / preview 環境へ接続する場合は、AI_AGENT_API_ENDPOINT を設定するか、createClient({ baseUrl: "..." }) を使って接続先を上書きしてください。
getSession() には、この API が返す以下の形式の値をそのまま返せば動作します。
type AgentSession = {
token: string;
expiresAt: string;
};4-2. MCP エンドポイントでトークンを検証する
アプリ固有のツールを AI Agent に公開する場合は、MCP エンドポイント側で受け取ったトークンを検証します。
このとき、サーバー環境に MCP_TOKEN_SECRET の設定が必要です。
@super_studio/ecforce-ai-agent-server/mcp-auth には、MCP トークンを扱うためのユーティリティが含まれています。
import { getMcpToken } from "@super_studio/ecforce-ai-agent-server/mcp-auth";
export async function GET(req: Request) {
const mcpToken = getMcpToken(req);
if (!mcpToken) {
return new Response("Unauthorized", { status: 401 });
}
return new Response("ok");
}トークンの中身を利用したい場合は decodeMCPToken() を使います。
import { decodeMCPToken } from "@super_studio/ecforce-ai-agent-server/mcp-auth";
export async function GET(req: Request) {
const authHeader = req.headers.get("authorization");
const token = authHeader?.replace(/^Bearer\s+/i, "");
if (!token) {
return new Response("Unauthorized", { status: 401 });
}
const payload = await decodeMCPToken(token);
return Response.json({
source: payload.source,
user: payload.user,
});
}