この記事では、Autonomous AI Database の Select AI Agent を使って、複数ターンの会話に対応する「返品対応エージェント」を構築します。エージェントは顧客からの返品依頼に応答し、データベース上の注文ステータスを更新します。
本記事で構築する返品対応エージェントには、次の 3 つの特徴があります:
-
Function ベースのツールを使用
- ステータス更新処理は Oracle Database 内の PL/SQL Function をツールとしてエージェントに呼び出させます。
- これにより、データベースのビジネスロジックをそのまま再利用できます。
-
大規模言語モデルに Autonomous AI Database の「Gen AI」を利用
- エージェントの会話能力は OCI の Gen AI サービスで動作します。
- 外部 LLM サービス不要で Oracle DB 内だけで完結します。
-
返品処理に特化したカスタマーサービス・エージェントの実装例
- 「不要になった」「到着が遅れた」「不良品」「箱の破損」などの理由を聞き取り、適切なフローで処理を案内します。
- 最終的には注文ステータスをデータベースに反映し、マルチターンで自然な顧客応対を行います。
事前準備
以下の記事を事前に確認してください:
検証環境
OCI Tokyoリージョンに構築した 26ai の Autonomous AI Database を利用しました。
作業は Database Actions と SQL Developer 上で実施しました。
作業手順
本例で作成するオブジェクト:
| 種類 | 名称 |
|---|---|
| エージェント | Customer_Return_Agent |
| ツール | Update_Order_Status_Tool |
| タスク | Handle_Product_Return_Task |
| チーム | Return_Agency_Team |
サンプルデータ作成
まず、顧客情報と注文ステータスのサンプルデータを用意します。
CREATE TABLE CUSTOMERS (
customer_id NUMBER(10) PRIMARY KEY,
name VARCHAR2(100),
email VARCHAR2(100),
phone VARCHAR2(20),
state VARCHAR2(2),
zip VARCHAR2(10)
);
INSERT INTO CUSTOMERS (customer_id, name, email, phone, state, zip) VALUES
(1, 'アリス・トンプソン', 'alice.thompson@example.com', '555-1234', 'NY', '10001');
INSERT INTO CUSTOMERS (customer_id, name, email, phone, state, zip) VALUES
(2, 'ボブ・マルティネス', 'bob.martinez@example.com', '555-2345', 'CA', '94105');
INSERT INTO CUSTOMERS (customer_id, name, email, phone, state, zip) VALUES
(3, 'キャロル・チェン', 'carol.chen@example.com', '555-3456', 'TX', '73301');
INSERT INTO CUSTOMERS (customer_id, name, email, phone, state, zip) VALUES
(4, 'デイビッド・ジョンソン', 'david.johnson@example.com', '555-4567', 'IL', '60601');
INSERT INTO CUSTOMERS (customer_id, name, email, phone, state, zip) VALUES
(5, 'エヴァ・グリーン', 'eva.green@example.com', '555-5678', 'FL', '33101');
CREATE TABLE CUSTOMER_ORDER_STATUS (
customer_id NUMBER(10),
order_number VARCHAR2(20),
status VARCHAR2(30),
product_name VARCHAR2(100)
);
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(2, '7734', '配達済み', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(1, '4381', '配達待ち', 'スマートフォン保護ケース');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(2, '7820', '配達済み', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(3, '1293', '返品待ち', 'スマートフォンスタンド(金属)');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(4, '9842', '返品済み', 'スマートフォンバックアップストレージ');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(5, '5019', '配達済み', 'スマートフォン保護ケース');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(2, '6674', '配達待ち', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(1, '3087', '返品済み', 'スマートフォンスタンド(金属)');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(3, '7635', '返品待ち', 'スマートフォンバックアップストレージ');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(4, '3928', '配達済み', 'スマートフォン保護ケース');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(5, '8421', '配達待ち', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(1, '2204', '返品済み', 'スマートフォンスタンド(金属)');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(2, '7031', '配達待ち', 'スマートフォンバックアップストレージ');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(3, '1649', '配達済み', 'スマートフォン保護ケース');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(4, '9732', '返品待ち', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(5, '4550', '配達済み', 'スマートフォンスタンド(金属)');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(1, '6468', '配達待ち', 'スマートフォンバックアップストレージ');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(2, '3910', '返品済み', 'スマートフォン保護ケース');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(3, '2187', '配達済み', 'スマートフォン充電ケーブル');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(4, '8023', '返品待ち', 'スマートフォンスタンド(金属)');
INSERT INTO CUSTOMER_ORDER_STATUS (customer_id, order_number, status, product_name) VALUES
(5, '5176', '配達済み', 'スマートフォンバックアップストレージ');
エージェント作成
エージェント「Customer_Return_Agent」を作成し、プロファイル「GENAI」と返品リクエストを管理する役割を設定します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
agent_name => 'Customer_Return_Agent',
attributes => '{"profile_name":"GENAI","role":"あなたは顧客の返品依頼に対応する経験豊富なカスタマーリターン担当者です。"}'
);
END;
/
ツール作成
ステータス更新用 PL/SQL 関数を作成し、それでエージェントツール「Update_Order_Status_Tool」を作成します。
CREATE OR REPLACE FUNCTION UPDATE_CUSTOMER_ORDER_STATUS (
p_customer_name IN VARCHAR2,
p_order_number IN VARCHAR2,
p_status IN VARCHAR2
) RETURN CLOB IS
v_customer_id customers.customer_id%TYPE;
v_row_count NUMBER;
BEGIN
SELECT customer_id INTO v_customer_id FROM customers WHERE name = p_customer_name;
UPDATE customer_order_status SET status = p_status WHERE customer_id = v_customer_id AND order_number = p_order_number;
v_row_count := SQL%ROWCOUNT;
IF v_row_count = 0 THEN
RETURN '更新対象のレコードが見つかりません。';
ELSE
RETURN '更新が成功しました。';
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN 'エラー: ' || SQLERRM;
END;
/
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
tool_name => 'Update_Order_Status_Tool',
attributes => '{"instruction": "このツールは返品ステータスの変更をデータベースに反映します。更新前に必ずユーザーの氏名と注文番号を確認してください",
"function" : "update_customer_order_status"}',
description => '顧客の注文ステータスをデータベーステーブルで更新するためのツール。'
);
END;
/
タスク作成
タスク「Handle_Product_Return_Task」を作成し、返品理由(不要になった、到着が遅れた、箱の破損、または不良品)を確認するフローを定義します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TASK(
task_name => 'Handle_Product_Return_Task',
attributes => '{"instruction": "顧客からの返品依頼を処理してください:{query}' ||
'1. 返品理由(不要になった、到着が遅れた、箱の破損、または不良品)を確認してください' ||
'2. 不要になった場合:' ||
' a. お客様に、送料はお客様負担で当社へ返送していただく旨を案内してください。' ||
' b. Update_Order_Status_Tool を使用して注文ステータスを 良品返品待ち に更新してください。' ||
'3. 到着が遅れた場合:' ||
' a. お客様に返金を希望するか確認してください。' ||
' b. お客様が返金を希望する場合、返金完了を案内し、注文ステータスを 返金完了 に更新してください' ||
'4. 不良品または箱の破損の場合:' ||
' a. 交換か返金か希望を確認してください' ||
' b. 交換の場合、交換品の発送と不良品返送用のラベル送付を案内し、注文ステータスを 不良品返品待ち に更新してください' ||
' c. 返金の場合、返品用ラベルの印刷と返送を案内し、注文ステータスを 返金待ち に更新してください' ||
'5. 返品または返金が完了した後、他にお手伝いできることがあるか確認してください。' ||
' ユーザーが不要であればタスクを終了してください",
"tools": ["Update_Order_Status_Tool"]}'
);
END;
/
チーム作成
エージェントチーム「Return_Agency_Team」を作成し、「Customer_Return_Agent」をエージェントとして設定します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TEAM(
team_name => 'Return_Agency_Team',
attributes => '{"agents":[{"name":"Customer_Return_Agent","task":"Handle_Product_Return_Task"}],"process":"sequential"}'
);
END;
/
エージェントチームの実行
以下のように、プロンプトの先頭に select ai agent を付けて対話します。実行前に対象チームを会話セッションに設定してください。
EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('Return_Agency_Team');
SELECT DBMS_CLOUD_AI_AGENT.GET_TEAM FROM DUAL;
select ai agent スマートフォンケースを返品したいです;
select ai agent 回答:スマートフォンケースを返品したい理由を教えてください。不要になった、到着が遅れた、箱の破損、または不良品のどれかになりますか?
select ai agent 商品に不具合があります;
select ai agent 回答:交換か返金のどちらを希望しますか?
select ai agent 交換を希望します;
select ai agent 回答:お客様の名前と注文番号を教えてください。
select ai agent 私はボブ・マルティネスで、注文番号は7820です;
select ai agent 回答:交換品の発送と不良品返送用のラベル送付について、他にお手伝いできることがありますか?
select ai agent いいえ、問題ありません。ありがとうございます;
select ai agent 回答:以上で返品処理は完了です。ご不便をおかけして申し訳ございません。ご利用ありがとうございました。
Select AI エージェントは上記の回答でお客様と会話して、下記のようにデータベースの注文ステータスを更新します。
補足
- Database Actions の SQL ワークシートや APEX では
SELECT AI AGENT文を直接実行できないため、必要に応じてDBMS_CLOUD_AI_AGENT.RUN_TEAMを用いた PL/SQL 実行で同様の対話を再現できます。 -
SET_TEAMはセッション単位の設定です。対話を行う同一セッション内で実行してください。

