はじめに
この記事は下記の記事の続きとなります。
前回は宛先を動的に変えながらメールを送るAgent Toolを作成しAgent経由でメール送信しました。
今回はDB検索用のAgentと前回作成したメール送信のAgentを組み合わせて、DBから宛先となる顧客のメールアドレスと注文の状況を取得し、メールで報告するAgentをデータベースの機能だけで作りたいと思います。
この記事でやること
- DB検索Agentの作成
- メール送信Agent Toolの修正
- 上記2つのAgentを顧客対応AgentとしてAgent Team化しDB検索した内容に応じた宛先と内容でメールを送信
検証環境
環境全体像
今回Agentを構築する環境は以下のようなイメージです。
CUSTOMERSテーブルはADB内に存在し、ordersとinventoryテーブルはPostgreSQL上に存在するデータをDBLINKで参照するSidecar構成になっています。

DB内の格納データ
DBの中には以下のデータが格納されています。
- メタデータ
| 項目 | 内容 |
|---|---|
| スキーマ名 | AI_USER |
| CUSTOMERS |
物理テーブル(ADB上) 顧客マスタ。顧客名( CUST_NAME: ギガテンドー等)、ランク、連絡先(CONTACT_NAME)、メール(EMAIL) |
| INVENTORY |
View(DBLINKでPostgreSQL参照) 製品マスタ。製品ID( PROD_ID)、在庫数(STOCK_QTY: 0〜500)、倉庫名(WH_NAME: 横浜/名古屋/福岡) |
| ORDERS |
View(DBLINKでPostgreSQL参照) 受注履歴。注文ID( ORD_ID)、製品ID(PROD_ID)、数量(QTY)、ステータス(Shipped/Pending/Cancelled) |
- 格納データのイメージ
SQL> select * from orders fetch first 5 rows only;
ORD_ID PROD_ID QTY ORD_DATE STATUS CUST_ID
_________ __________ ______ ____________ ____________ ___________
961 MTR-033 14 08-MAR-26 Cancelled CUST-048
962 MTR-028 9 12-FEB-26 Pending CUST-024
963 MTR-010 20 05-MAR-26 Shipped CUST-026
964 MTR-002 6 01-MAR-26 Pending CUST-029
965 MTR-013 2 20-FEB-26 Shipped CUST-008
SQL> select * from inventory fetch first 5 rows only;
PROD_ID STOCK_QTY WH_NAME UPDATE_AT
__________ ____________ __________ ____________
MTR-001 475 福岡センター 26-FEB-26
MTR-002 443 福岡センター 26-FEB-26
MTR-003 291 名古屋ロジ 26-FEB-26
MTR-004 257 名古屋ロジ 26-FEB-26
MTR-005 125 名古屋ロジ 26-FEB-26
SQL> select * from customers fetch first 5 rows only;
ID CUST_NAME REGION RANK CONTACT_NAME EMAIL
___________ ____________ _________ ___________ _______________ _________________________
CUST-004 ハードバンク 東京 Silver 真田幸村 xxx@gmail.com
CUST-005 トニー電子 名古屋 Platinum 松永久秀 xxx@gmail.com
CUST-006 ギガテンドー 大阪 Gold 加藤清正 xxx@gmail.com
CUST-007 ワンツーアパレル 福岡 Silver 吉川元春 xxx@gmail.com
CUST-008 ロックエンス 東京 Platinum 上杉謙信 xxx@gmail.com
この3つのテーブルとViewに対して問い合わせを行うAgentを作成していきましょう。
DB検索Agentの作成
おさらいになりますが、Agentの作成は以下のStepで実施します。
| Step | 内容 |
|---|---|
| 1. Agent Toolの作成 | Agentに使用させるツールを定義します。組み込み済みのSQLツールを使用します。 |
| 2. Taskの作成 | Agentが実行するタスクを定義します。何をどのツールで処理するのかを指定するイメージです。 |
| 3. Agentの作成 | AgentにAIプロファイルと役割を設定します。 |
| 4. Agent Teamの作成 | どのAgentがどのタスクをどういう順で実施するのかを定義します。 |
| 5. 有効化 | Agent Teamが動作するできるように有効化します。 |
Toolの作成
まずはToolの作成です。
ToolのInstructionがAgentの動作を大きく左右するため、しっかりと書きましょう。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
-- DB検索用のTool名を指定します。
tool_name => 'SQL_TOOL',
-- attributesにToolの定義情報を入力します。
-- tool_typeにSQLを指定し、DB検索用Toolとして定義します。
-- tool_paramsにNL2SQL用のProfile名を指定します。
-- Instructionは丁寧に書くのが重要です。特にメール送信に必須の宛先情報は必ず取得するように指示します。
attributes => '{
"tool_type": "SQL",
"tool_params": {
"profile_name": "NL2SQL_PROFILE"
},
"instruction": "ユーザーの依頼内容に基づいてデータベースを検索するツールです。
後続のメール送信Taskで利用するため、対象顧客を特定したうえで、
CUSTOMERS表からCUST_NAME、CONTACT_NAME、EMAILを必ず取得してください。
EMAILはメール送信先として使用されます。
CONTACT_NAMEはメール本文の宛名として使用されます。
CUST_NAMEは顧客名として本文や確認結果に使用されます。
注文に関する問い合わせではORDERS表を検索し、ORD_ID、PROD_ID、QTY、
ORD_DATE、STATUS、CUST_IDを取得してください。
在庫や出荷見込みに関する問い合わせではINVENTORY表を検索し、
PROD_ID、STOCK_QTY、WH_NAME、UPDATE_ATを取得してください。
CUSTOMERS.CUST_ID = ORDERS.CUST_ID、
ORDERS.PROD_ID = INVENTORY.PROD_IDとして関連付けてください。
検索結果は次の形式で返してください:
CUST_NAME: <顧客名>,
CONTACT_NAME: <担当者名>,
EMAIL: <メールアドレス>,
RELATED_INFO: <問い合わせに関連する検索結果>。
RELATED_INFOには、注文番号、商品ID、数量、注文日、注文ステータス、
在庫数量、倉庫名、在庫更新日など、ユーザーの問い合わせに必要な情報を含めてください。
EMAILがNULLまたは見つからない場合は、メール送信不可であることを明確に返してください。"
}',
-- Toolの概要説明です。
description => 'DBから宛先情報、注文状況、在庫情報を検索するツール'
);
END;
TASKの作成
次はAgentが実施するTASKを、先ほど作成したToolを指定して作成します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TASK(
task_name => 'ORDER_STATUS_SQL_TASK',
attributes => '{
"instruction": "ユーザーからの依頼: {query}。
SQL_TOOLを使って、対象顧客の宛先情報と問い合わせ内容に関連する
注文・在庫情報を検索してください。後続のメール送信Taskが利用できるよう、
結果には必ずCUST_NAME、CONTACT_NAME、EMAILを含め、
問い合わせに関連する情報をRELATED_INFOとしてまとめてください。
EMAILがNULLまたは見つからない場合は、メール送信不可であることを明確に
返してください。",
"tools": ["SQL_TOOL"],
"enable_human_tool": "false"
}',
description => '顧客宛先情報と注文・在庫情報を検索するTask'
);
END;
/
Agent作成
続いてAgentを作成します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
-- Agent名を指定します。
agent_name => 'DB_SEARCH_AGENT',
-- attributesにAgentの定義情報を入力します。
-- profile_nameにはAgentが利用するAI Profile名を指定します。
-- roleには、このAgentの役割を自然言語で定義します。
attributes => '{
"profile_name": "DYNAMIC_MAIL_AGENT_PROFILE",
"role": "あなたはデータベース検索を担当するエージェントです。ユーザーの依頼内容を理解し、
SQL検索Taskを通じて、後続のメール送信Taskに必要な宛先情報と問い合わせ関連情報を取得し
てください。検索結果には、メール送信先として使うEMAIL、宛名として使うCONTACT_NAME、
顧客名として使うCUST_NAMEが含まれるようにしてください。"
}',
-- Agentの概要説明です。
description => 'DBから宛先情報と問い合わせ関連情報を検索するAgent'
);
END;
/
動作確認(Agent Team作成)
AgentをAgent Teamにし、TASKと紐付けます。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TEAM(
team_name => 'DB_SEARCH_TEST_TEAM',
attributes => '{
"agents": [
{
"name": "DB_SEARCH_AGENT",
"task": "ORDER_STATUS_SQL_TASK"
}
],
"process": "sequential"
}',
description => 'DB検索Agent単体の動作確認用Team'
);
END;
/
完成したらAgent Teamをセットしましょう。
EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('DB_SEARCH_TEST_TEAM');
これにて準備完了です。
それでは早速、Agentに依頼をしてみましょう。
SQL> SELECT AI AGENT 'ギガテンドーの最新の注文状況を確認してください。後続のメール送信に使えるように、CUST_NAME、CONTACT_NAME、EMAI
L、RELATED_INFOの形式で返してください。';
RESPONSE
________________________________________________________
CUST_NAME: ギガテンドー,
CONTACT_NAME: 加藤清正,
EMAIL: xxx@gmail.com,
RELATED_INFO:
最新注文情報 - 注文ID: 385,
商品ID: MTR-032,
数量: 14,
注文日: 2026-03-11T00:00:00,
ステータス: Pending,
在庫数量: 350,
倉庫名: 名古屋ロジ,
在庫更新日: 2026-02-26T00:47:30
期待した回答形式で情報が得られています。
次は検索エージェントからの結果を受け取ってメールを送信するメール送信Agentを作成し、検索エージェントと組み合わせてAgent Teamにします。
メールAgentの作成
メールAgentを作成していきます。
メールAgentやToolとして登録するプロシージャは前回の記事で作成したものを流用します。
Agent TaskのみInstructionを検索Agentとの連携を前提とした内容に修正します。
Taskの作成
Taskについては、検索Agentからの出力を受け取った動作をするようにInstructionを修正します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TASK(
task_name => 'DYNAMIC_MAIL_TASK',
attributes => '{
"instruction": "前段のORDER_STATUS_SQL_TASKから受け取った検索結果を読み取り、
EMAILの値を送信先メールアドレスとして使用してください。
CONTACT_NAMEはメール本文の宛名として使用してください。
CUST_NAMEは顧客会社名、CONTACT_NAMEは顧客担当者名として本文冒頭に
使用してください。RELATED_INFOにはユーザーの問い合わせに関連する
注文状況、在庫状況、出荷見込みなどの情報が含まれます。
DYNAMIC_MAIL_TOOLを使い、p_recipientにはEMAILの値、
p_subjectには問い合わせ内容に応じた短く端的な件名、p_bodyには
CONTACT_NAME、CUST_NAME、RELATED_INFOを反映した丁寧な日本語メール
本文を指定してください。STATUSがPendingの場合は、注文は現在処理中である
こと、在庫情報が確認できている場合は出荷準備を進められる見込みであることを
本文に含めてください。EMAILがNULLまたは見つからない場合は、メール送信せず、
送信先メールアドレスが取得できなかったことをユーザーに伝えてください。
メール送信後は、使用した送信先メールアドレスをユーザーに伝えてください。",
"input": "ORDER_STATUS_SQL_TASK",
"tools": ["DYNAMIC_MAIL_TOOL"],
"enable_human_tool": "true"
}',
description => `SQL検索結果をもとにメール本文を作成して送信するTask`
);
END;
/
これにてメールAgentは今回作成したTASKにて動作してくれます。
顧客対応Agent Teamの作成
作成したDB_SEARCH_AGENTとDYNAMIC_MAIL_AGENTを組み合わせたAgent Teamを作成します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TEAM(
team_name => 'ORDER_STATUS_MAIL_TEAM',
attributes => '{
"agents": [
{
"name": "DB_SEARCH_AGENT",
"task": "ORDER_STATUS_SQL_TASK"
},
{
"name": "DYNAMIC_MAIL_AGENT",
"task": "DYNAMIC_MAIL_TASK"
}
],
"process": "sequential"
}',
description => 'DB検索結果をもとに注文状況メールを送信するTeam'
);
END;
/
作成したAgent Teamをセットします。
EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('ORDER_STATUS_MAIL_TEAM');
Agentを動かしてみる
早速Agentに仕事を依頼してみましょう。
SELECT AI AGENT
'ギガテンドーの最新注文日の注文状況を確認し、その内容を担当者宛に1通のメールで送信してください。その日に複数注文がある場合はすべて本文に含めてください。';
RESPONSE
___________________________________________________________________________
ギガテンドーの最新注文状況を確認し、担当者宛にメールを送信しました。
使用した送信先メールアドレス: xxx@gmail.com
Pendingの注文とCancelの注文の2件が存在するようです。
Pedingの注文に関しては在庫数を確認して出荷が進められる状況と説明をしています。
きちんと注文状況を確認して、メール送信してくれています。
SQLで見てみましょう。
SELECT
c.cust_id,
c.cust_name,
c.contact_name,
c.email,
o.ord_id,
o.prod_id,
o.qty,
o.ord_date,
o.status,
i.stock_qty,
i.wh_name,
i.update_at
FROM customers c
JOIN orders o
ON c.cust_id = o.cust_id
LEFT JOIN inventory i
ON o.prod_id = i.prod_id
WHERE c.cust_name = 'ギガテンドー'
AND o.ord_date = (
SELECT MAX(o2.ord_date)
FROM orders o2
JOIN customers c2
ON c2.cust_id = o2.cust_id
WHERE c2.cust_name = 'ギガテンドー'
)
ORDER BY
o.ord_id DESC;
CUST_ID CUST_NAME CONTACT_NAME EMAIL ORD_ID PROD_ID QTY ORD_DATE STATUS STOCK_QTY WH_NAME UPDATE_AT
___________ ____________ _______________ _________________________ _________ __________ ______ ____________ ____________ ____________ __________ ____________
CUST-006 ギガテンドー 加藤清正 xxx@gmail.com 691 MTR-016 17 11-MAR-26 Cancelled 241 名古屋ロジ 26-FEB-26
CUST-006 ギガテンドー 加藤清正 xxx@gmail.com 385 MTR-032 14 11-MAR-26 Pending 350 名古屋ロジ 26-FEB-26
Agentの言う通り、CancelとPendingの注文が存在しています。
STOCK_QTYから先ほどのPendingの注文の在庫が存在していることがわかるので、適当な回答をしているわけではないということがわかります。
先ほどのメールの内容は正しいと確認ができました。
他の宛先にも送ってみる
DBの顧客情報をもとに正しい宛先にメールを送信していることを、裏付けるため、別のアドレスを持つ顧客向けの連絡も可能か確認してみます。
ヨツビシ交易のEMAILを先ほどとは別のEMAILアドレスにUPDATEしました。
ヨツビシ交易のEMAILは末尾が0です。

ヨツビシ交易宛で先ほどのギガテンドーと同じ依頼をしてみましょう。
SELECT AI AGENT
'ヨツビシ交易の最新注文日の注文状況を確認し、その内容を担当者宛に1通のメールで送信してください
。その日に複数注文がある場合はすべて本文に含めてください。';
RESPONSE
__________________________________________________
メールを送信しました。使用した送信先メールアドレス: yyy0@gmail.com
メールを確認してみましょう。
きちんとDB内に格納されているヨツビシ交易の担当者メールアドレスに送信されています。

きちんとAgentがDB内のメールアドレスを確認してメール送信していることが確認できました。
まとめ
今回は、Select AI Agentのカスタムツールを使って、DB内に格納された顧客情報を確認し、メール送信を行う顧客対応AgentをDatabaseだけで実装しました。組み込み済みのメール送信ツールも存在しますが、現状そちらではTool内にハードコードした宛先にしかメールが送れません。そんな時は今回のようにToolを自作し、Agent Toolとして登録することでSelect AI Agentにやらせたい動作をさせることができます。
様々なカスタムツールを作成して、いろんなIn-Database Agentを作成してみてください。


