2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle ADB Select AI Agent入門 ~In-Database AgentによるDB検索とメール送信~

2
Last updated at Posted at 2026-04-10

unnamed (1).png

はじめに

Oracle Autonomous AI Database(ADB) には、データベースの内部でAI Agentを構築できる「Select AI Agent」という機能があります。
今回はこの機能を使って、DB上のデータを参照しながら処理を実行するAI Agentを作ってみます。
参照するデータはADBの AI Proxy Database を活用し、ADB上のデータだけでなくADB外のPostgreSQLのデータもADBからAgentが参照できるように構成します。
(AI Proxy Databaseの検証は別の記事で実施しているのでそちらもご参照ください。)

このようにデータソースをADBに集約し、データの近くでAI Agentを動かすことで、シンプルな構成でAI活用基盤が構成できます。

この記事でやること

この記事で実施することは以下の3つです。

  • DBの情報を検索するAgentの構築
  • メール送信を行うAgentの構築
  • 2つのAgent同士を組み合わせたチームとして動作

単純に動かすだけでなく、簡単ですがうまくいかなかった点やチューニングのポイントも含めて整理しました。

環境構築

早速環境構築を進めていきましょう。

前提

環境はこちらの記事の検証で利用したものを流用しており、STEP2までの構築とStep3-3のADBへのデータ投入が完了した状態と同等です。
ですので、ADBおよびPostgreSQL環境の構築設定とベースとなるデータの投入は完了している状態です。

PostgreSQL上のデータ

項目 内容
スキーマ名 order_system
inventory 100件(製品マスタ)
製品ID(MTR/SNS/CB)、在庫数(0〜500)、倉庫名(横浜/名古屋/福岡)
orders 1,000件(受注履歴)。過去30日間の注文、ステータス(Shipped/Pending/Cancelled)、顧客ID

ADB上のデータ

項目 内容
スキーマ名 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)

Table/VIEWの情報

SQL> SELECT column_name, data_type, data_length
  2  FROM user_tab_cols
  3  WHERE table_name = 'ORDERS'
  4* ORDER BY column_id;

COLUMN_NAME    DATA_TYPE       DATA_LENGTH 
______________ ____________ ______________ 
ORD_ID         NUMBER                   22 
PROD_ID        VARCHAR2                 20 
QTY            NUMBER                   22 
ORD_DATE       DATE                      7 
STATUS         VARCHAR2                 20 
CUST_ID        VARCHAR2                 20 

6 rows selected. 

SQL> SELECT column_name, data_type, data_length
  2  FROM user_tab_cols
  3  WHERE table_name = 'INVENTORY'
  4* ORDER BY column_id;

COLUMN_NAME    DATA_TYPE       DATA_LENGTH 
______________ ____________ ______________ 
PROD_ID        VARCHAR2                 20 
STOCK_QTY      NUMBER                   22 
WH_NAME        VARCHAR2                 50 
UPDATE_AT      DATE                      7 

SQL> SELECT column_name, data_type, data_length
  2  FROM user_tab_cols
  3  WHERE table_name = 'CUSTOMERS'
  4* ORDER BY column_id;

COLUMN_NAME     DATA_TYPE       DATA_LENGTH 
_______________ ____________ ______________ 
CUST_ID         VARCHAR2                 10 
CUST_NAME       VARCHAR2                100 
REGION          VARCHAR2                 50 
RANK            VARCHAR2                 20 
CONTACT_NAME    VARCHAR2                100 
EMAIL           VARCHAR2                255 

6 rows selected. 

構築作業

以下の流れで実施します。

  1. 下準備
  2. DB検索用Agentの作成
  3. メール送信用Agentの作成
  4. 上記2タイプのAgentを組み合わせたAgent Temaの作成

下準備

Agent作成の前にデータ投入や権限付与などの下準備をします。

データの投入

ADB上のCUSTOMERSテーブルに列を追加し、担当者とそのメールアドレスの情報を投入します。
担当者のメールアドレスとして私のメールアドレスを登録しています。
データがないときの動作用にデータの一つはNullを入れておきます。

SQL> UPDATE CUSTOMERS 
  2  SET CONTACT_NAME = '織田信長', 
  3      EMAIL = '*****@gmail.com' 
  4* WHERE CUST_NAME = 'ヨツビシ交易';

1 row updated.

SQL> UPDATE CUSTOMERS 
  2  SET CONTACT_NAME = '豊臣秀吉', 
  3      EMAIL = '*****@gmail.com'
  4* WHERE CUST_NAME = 'ミツカド決済銀行';

1 row updated.

SQL> UPDATE CUSTOMERS 
  2  SET CONTACT_NAME = '徳川家康', 
  3      EMAIL = NULL 
  4* WHERE CUST_NAME = 'トヨノキ自走車';

1 row updated.

SQL> Commit;

Commit complete.

Agent作成権限の付与

Select AI Agentを作成するための権限を付与していきます。admin等の管理者権限を持つユーザーでログインし、作成済みのai_userに付与します。

GRANT EXECUTE on DBMS_CLOUD_AI_AGENT to ai_user;

Grant succeeded.

クレデンシャルの作成

LLMを利用する用のクレデンシャルを作成します。好きな名前をつけてください。私はOCI_CREDで作成しました。

BEGIN
    DBMS_CLOUD.CREATE_CREDENTIAL(
        credential_name => '好きな名前',
        user_ocid       => 'ユーザーのOCID',
        tenancy_ocid    => 'テナンシのOCID',
        private_key     => 'APIの秘密鍵',
        fingerprint     => 'APIキーのフィンガープリント'
    );
END;
/

プロファイルの作成

Select AI Agentの利用には、Agentがどのクレデンシャルを使ってどのLLMにアクセスし、どのオブジェクトを利用するかを指定するプロファイルの作成が必要です。

Agent用プロファイルの作成

AI Agent用のプロファイルも作成しておきます。
このプロファイルを後ほど作成するAgentにセットしてあげることで、AgentがLLMとオブジェクトへのアクセスが可能になります。

BEGIN
  DBMS_CLOUD_AI.CREATE_PROFILE(
    profile_name =>'NL2SQL_PROFILE',
    attributes   =>'{"provider": "oci",
        "credential_name": "OCI_CRED",
        "region":"us-ashburn-1",
        "model": "xai.grok-4",
        "object_list": [
                            {"owner": "ai_user", "name": "ORDERS"},
                            {"owner": "ai_user", "name": "INVENTORY"},
                            {"owner": "ai_user", "name": "CUSTOMERS"}
                        ]
                    }'
  );
END;
/

DB検索Agentの作成

それではAgentを作成します。
ADBには組み込み済みのツールが存在しており、Agentはこれらのツールを使ってタスクを実行することができます。当然、自分でツールを作成することも可能ですが、今回は組み込み済みのツールを利用するAgentを作成します。
組み込み済みツールには以下があります。

組み込みツール

項目 内容
SQL データベース・クエリ実行
自然言語をSQLに変換し、DB内のテーブルやビューからデータを取得・分析する。
RAG ベクトル検索による回答生成
OCI OpenSearch等のベクトル・ストアと連携し、マニュアル等の非構造化データから回答を探す。
WEBSEARCH 外部検索エンジン連携
Google Search等を利用して、最新のニュースや市場価格などDB外の情報を取得する。
NOTIFICATION 外部通知(EMAIL / SLACK)
生成された回答や特定のデータを、メール送信(EMAIL)やSlack(SLACK)への投稿を通じて外部へ配信する。

NL2SQLを実行するAgentの構築

まずはNL2SQLの簡単なAgent構築から試しましょう。
NL2SQLのAgentは事前構成済みのため、簡単に設定が可能です。
必要な作業としては以下の流れです。

Step 内容
1. Agent Toolの作成 Agentに使用させるツールを定義します。組み込み済みのSQLツールを使用します。
2. Taskの作成 Agentが実行するタスクを定義します。何をどのツールで処理するのかを指定するイメージです。
3. Agentの作成 AgentにAIプロファイルと役割を設定します。
4. Agent Teamの作成 どのAgentがどのタスクをどういう順で実施するのかを定義します。
5. 有効化 Agent Teamが動作するできるように有効化します。

1. NL2SQL Agent Toolの作成

Customersテーブルの顧客情報を参照するAgentのツールを作成します。NL2SQL_TOOLという名前にします。

BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
        tool_name  => 'NL2SQL_TOOL',
        attributes => '{
          "instruction": "顧客の担当者情報を参照する際に利用",
          "tool_type": "SQL",
          "tool_params": {"profile_name": "NL2SQL_PROFILE"}}'
    );
END;
/

2. タスクの作成

ユーザーの問い合わせに対してNL2SQLツールを使って回答をするというタスクを作成します。SQL_TASKというタスクにします

BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TASK(
        task_name => 'SQL_TASK',
        attributes => 
            '{
                "instruction": "ユーザからの質問: {query}。",
                "tools": ["NL2SQL_TOOL"],
                "enable_human_tool": "False"
            }'
    );
END;
/

3. Agentの作成

AIプロファイルとロールを指定しAgentを作成します。CUST_SEARCH_AGENTという名前にしました。

BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
        agent_name => 'CUST_SEARCH_AGENT',
        attributes => '{"profile_name": "NL2SQL_PROFILE",
           "role": "データベース内のテーブルから顧客の名前や連絡先などの顧客情報を取得"
        }'
    );
END;
/

4. Agentチームの作成

作成したAgentにタスクを割り当てチーム化します。(今は1つのAgentですが。。)

BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TEAM(  
        team_name  => 'CUSTOMER_SEARCH_AGENT_TEAMS',
        attributes => '{"agents": [
            {"name":"CUST_SEARCH_AGENT",
             "task":"SQL_TASK"}],
        "process": "sequential"
    }');
END;
/

5. 有効化

忘れずに有効化しましょう。

EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('CUSTOMER_SEARCH_AGENT_TEAM');

Agentに仕事を頼んでみる

ひとまずNL2SQL_Agentの設定が完了しました。
動作確認をしてみましょう。
Agentを呼び出すには
select ai agent + プロンプト
と入力します。
まずはAgentの役割を確認します。

SQL> select ai agent あなたは誰ですか;

RESPONSE                                                         
________________________________________________________________ 
私はCUST_SEARCH_AGENTです。データベースから顧客の名前や連絡先などの情報を取得するためのエージェントです。    

きちんと役割を果たすか確認してみましょう。

SQL> select ai agent ヨツビシ交易の担当者とメールアドレス教えて;

RESPONSE                                                
_______________________________________________________ 
ヨツビシ交易の担当者は織田信長さんで、メールアドレスはxxxx@gmail.comです。  

問題なさそうです。

Null値を入れたところはどうでしょうか。

SQL> select ai agent トヨノキ自走車の担当者とメールアドレス教えて;

RESPONSE                                                                 
________________________________________________________________________ 
トヨノキ自走車の担当者は徳川家康さんですが、メールアドレスはデータベースに登録されていません。追加情報を必要とする場合はお知らせください。    

きちんと動作していますね!

参考: Agentに関係のない仕事を頼むとどうなるか

現在作成したAgentはCUSTOMERSテーブルを参照する役割を与えています。しかし、クレデンシャルにはCUSTOMERSテーブル以外もオブジェクトとして指定しており、アクセスが可能な状態です。
全然関係のないテーブルにアクセスさせてみるとどうなるのか確認してみましょう。
PostgreSQL上のORDERSテーブルをAI Proxy Databaseで参照可能な状態になっていますので、このORDERSテーブルへのアクセスが必要な問い合わせをCUSTOMER_SEARCH_AGENT_TEAMに投げてみます。

SQL> select ai agent オーダーは何件ある?;

RESPONSE             
____________________ 
オーダーの総件数は1000件です。  


-- SQLで確認
SQL> SELECT COUNT(*) AS total_orders FROM ORDERS;

   TOTAL_ORDERS 
_______________ 
           1000 

きちんと正しい結果を返してくれています。
SQL検索ツールしか渡していないので検索という枠は出ませんが、Agentがリモート表に対するアクセスも可能であること、定義した仕事に関連しないテーブルでもある程度融通を利かせて対応してくれることがわかりました。

メールエージェントの作成

先ほどのNL2SQL AgentはDBから情報を参照するAgentでした。
次はNotificationツールのEMAILを利用するメール配信Agentを試してみたいと思います。
Agent作成の流れは先ほどと同様ですが、メールサーバーの設定を別途実施します。
こちらを参考に進めます。

ADBからのメール送信の設定

まずはADBから手動でメールを送れるように設定を進めます。

SMTPの構成

OCIコンソールのナビゲーションメニューを開き、「開発者サービス」を選択します。「アプリケーション統合」の下にある「メール配信」を選択します。
image.png
画面左のメニューから「構成」を選択すると各種送信情報が確認できます。
image.png

SMTP資格証明の作成

メールの送信時の認証のためのSMTP資格証明を生成します。
OCIコンソールにて画面右上の「プロファイル」から「アイデンティティドメイン」を選択します。
image.png
現在のドメインを選択し、自分のユーザー名を選択してください。
image.png
image.png
すると、SMTP資格証明というタブが出てくるので選択し、資格証明を生成します。説明は適当に入れてください。
image.png
生成されたユーザー名とパスワードを保管しておきます。
image.png

電子メール配信の承認済送信者を作成

送信元となるメールアドレスを登録し、承認済み送信者とします。
再び「開発者サービス」>「電子メール配信」を選択し、承認済み送信者を設定します。
image.png

Access Control Entry(アクセス制御エントリ)の作成

Access Control EntryACE)はデータベースから、「どのユーザーが」「どこの外部サイト(ホスト)の」「どのポート」に通信していいかを定義するものです。

プロシージャの実行権限付与

adminでログインしてai_userに権限を与えます。

SQL> GRANT EXECUTE ON DBMS_NETWORK_ACL_ADMIN TO AI_USER;

Grant succeeded.

プロシージャの実行

AI_USERにてACEの設定を実施しました。

BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host => 'smtp送信情報のエンドポイント',
    lower_port => 587,
    upper_port => 587,
    ace => xs$ace_type(privilege_list => xs$name_list('SMTP'),
                       principal_name => 'AI_USER',
                       principal_type => xs_acl.ptype_db));
END;
/

メール送信用PL/SQLの作成

SEND_MAILというプロシージャーを作成しコンパイルします。
マニュアルのコードのままだと日本語で文字化けするため少し改良しています。

CREATE OR REPLACE PROCEDURE SEND_MAIL (
  msg_to varchar2,
  msg_subject varchar2,
  msg_text varchar2 ) 
IS
  mail_conn utl_smtp.connection;
  
  -- 【ここを書き換え!】
  username varchar2(1000):= '(OCIで発行したSMTPユーザー名)';
  passwd varchar2(100)  := '(OCIで発行したSMTPパスワード)'; 
  msg_from varchar2(100) := '(承認済送信者のメールアドレス)';
  mailhost VARCHAR2(100) := 'smtp.email.ap-tokyo-1.oci.oraclecloud.com'; -- 自分のリージョン
  -- 【書き換えここまで】

BEGIN
  mail_conn := UTL_smtp.open_connection(mailhost, 587);
  utl_smtp.starttls(mail_conn);
  UTL_SMTP.AUTH(mail_conn, username, passwd, schemes => 'PLAIN');
  
  utl_smtp.mail(mail_conn, msg_from);
  utl_smtp.rcpt(mail_conn, msg_to);
  
  UTL_smtp.open_data(mail_conn);
 
  -- ヘッダー部分:UTF-8であることを宣言
  UTL_SMTP.write_data(mail_conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
  UTL_SMTP.write_data(mail_conn, 'To: ' || msg_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(mail_conn, 'From: ' || msg_from || UTL_TCP.crlf);
  -- 日本語の件名対応
  UTL_SMTP.write_raw_data(mail_conn, utl_raw.cast_to_raw('Subject: ' || msg_subject || UTL_TCP.crlf));
  UTL_SMTP.write_data(mail_conn, 'Content-Type: text/plain; charset=UTF-8' || UTL_TCP.crlf);
  UTL_SMTP.write_data(mail_conn, 'Content-Transfer-Encoding: 8bit' || UTL_TCP.crlf || UTL_TCP.crlf);
  
  -- 本文:RAWデータとして送信することで文字化けを防ぐ
  UTL_SMTP.write_raw_data(mail_conn, utl_raw.cast_to_raw(msg_text || UTL_TCP.crlf));
  
  UTL_smtp.close_data(mail_conn);
  UTL_smtp.quit(mail_conn);

EXCEPTION
  WHEN OTHERS THEN
    UTL_smtp.quit(mail_conn);
    dbms_output.put_line('Error: ' || sqlerrm);
END;
/

メールを送ってみる

コンパイルしたPL/SQLを実行してメールを送ってみましょう。
今回は私のGmailアドレスに送ります。

BEGIN
    SEND_MAIL(
        msg_to      => 'xxx@gmail.com', -- ★ここに自分の受信用アドレス
        msg_subject => 'ADBからのデモメール成功',
        msg_text    => 'Cust_Searchエージェントの準備が整いました!'
    );
END;
/

Gmailを確認してみましょう。
image.png
無事に届いていました。(迷惑メールフォルダに。。)

これにてADBからメールを送信する準備が整いました。
次はAgentからの送信です。

Agentからのメール送信

次にメール送信Agentからメールを送信するように構成します。作成のStepはSQL検索Agentと同様です。

Agentプロファイルの作成

先ほどのDB検索Agent同様にプロファイルの作成から実施します。

BEGIN
  DBMS_CLOUD_AI.CREATE_PROFILE(
    profile_name =>'MAIL_AGENT_PROFILE',
    attributes   =>'{"provider": "oci",
        "credential_name": "OCI_CRED",
        "region":"us-ashburn-1",
        "model": "xai.grok-4",
        "object_list": [
                            {"owner": "ai_user", "name": "ORDERS"},
                            {"owner": "ai_user", "name": "INVENTORY"},
                            {"owner": "ai_user", "name": "CUSTOMERS"}
                        ]
                    }'
  );
END;
/

メール用のクレデンシャル作成

SMTPアクセス用のクレデンシャルを作成します。
ユーザー名とパスワードは先ほどのメール設定時に生成したSMTPの資格証明を入力します。
EMAIL_CREDという名前にしました。

BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => 'EMAIL_CRED',
    username => '<SMTP username>',
    password => '<SMTP password>');
END;
/

SMTPアクセス用ACEの設定

AI_USERにてACEの設定を実施します。先ほど実施済みならSKIPして問題ないです。

BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host => 'smtp送信情報のエンドポイント',
    lower_port => 587,
    upper_port => 587,
    ace => xs$ace_type(privilege_list => xs$name_list('SMTP'),
                       principal_name => 'AI_USER',
                       principal_type => xs_acl.ptype_db));
END;
/

Agent Toolの作成

メール送信を実施するツールを作成します。EMAILというツールを作成しました。

-- 既存のToolがある場合は削除
-- EXEC DBMS_CLOUD_AI_AGENT.DROP_TOOL('EMAIL');

BEGIN
  DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
    tool_name  => 'EMAIL',
    attributes => '{"tool_type": "NOTIFICATION",
                    "tool_params": {"notification_type" : "EMAIL",
                                    "credential_name": "EMAIL_CRED",
                                    "recipient": "宛先アドレス@gmail.com",
                                    "smtp_host": "smtp.email.us-ashburn-1.oci.oraclecloud.com",
                                    "sender": "送信元アドレス@gmail.com"}
                                    }'
  );
END;
/

Agent Taskの作成

Agentにやってもらうタスクを指定します。
Generata_Email_Taskというタスクを作成し、ツールにはEMAILツールを指定します。

-- 既存のTASKがある場合は削除
-- EXEC DBMS_CLOUD_AI_AGENT.DROP_TASK('Generate_Email_Task');

BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TASK(
task_name => 'Generate_Email_Task',
attributes => '{"instruction": "指定されたアドレス宛に、日本語のメールを作成してください。",
                "tools" : ["EMAIL"],
                "enable_human_tool" : "false"
                }'
   );
END;
/

Agent作成

MAIL_AGENTというAgentを作成しました。ToolにはEMAIL、プロファイルにはMAIL_AGENT_PROFILEを指定します。

-- 既存のAGENTがある場合は削除
-- EXEC DBMS_CLOUD_AI_AGENT.DROP_AGENT('MAIL_AGENT');

BEGIN
  DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
    agent_name => 'MAIL_AGENT',
    attributes => '{
      "profile_name": "MAIL_AGENT_PROFILE",
      "role": "あなたはメール送信の実行責任者です。ユーザーがプロンプトで指定したメールアドレスへのメール送信を実行します。",
      "tools": [
        {
          "tool_name": "EMAIL",
          "description": "メール送信ツール。"
        }
      ]
    }'
  );
END;
/

Agent Team作成

CUSTOMER_NOTIFICATION_TEAMというAgentチームを作成します。

-- 既存のTEAMがある場合は削除
--EXEC DBMS_CLOUD_AI_AGENT.DROP_TEAM('EMAIL_AGENT_TEAM');
BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TEAM(  
        team_name  => 'EMAIL_AGENT_TEAM',
        attributes => '{"agents": [
            {"name":"MAIL_AGENT","task":"Generate_Email_Task"}],
        "process": "sequential"
    }');
END;
/

有効化

忘れず有効化します。

EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('EMAIL_AGENT_TEAM');

Agentからのメール送信

Agentからメールが送れるか試してみましょう。

SQL> select ai agent xxx@gmail.comにテストメールを送信してください。;

RESPONSE                                         
________________________________________________ 
テストメールをxxx@gmail.comに送信しました。ご確認ください。    

image.png
きちんと届きました!

プロンプトを変えてみます。

SQL> select ai agent xxx@gmail.comに春の挨拶メールを送信してください。;

RESPONSE                                          
_________________________________________________ 
春の挨拶メールをxxx@gmail.comに送信しました。ご確認ください。  

image.png
春にふさわしい挨拶が届きました。

receipientに登録していないアドレス宛の送信

Agent Toolのなかにrecepientとして指定した宛先へは送信ができました。それ以外だとどうなるか確認してみます。

-- receipientに登録していないアドレス宛の送信
SQL> select ai agent yyy@gmail.comにテストメールを送信してください。;

RESPONSE                                       
______________________________________________ 
テストメールをyyy@gmail.comに送信しました。ご確認ください。    

送信したという風には回答が得られました。しかし、メールボックスを見ても受信は確認できませんでした。
Tool内のrecepientで指定した宛先のみ送信が可能なようです。

SQL AgentとMail Agentの組み合わせ

では最後にSQLで取得した情報をメールの内容に盛り込んで送信するAgent Teamを構成してみたいと思います。

幅広く検索できるようにDB検索のAgentを再構築します。

DB検索Agent

-- Tool作成 (SQL_TOOL)
BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
        tool_name  => 'SQL_TOOL',
        attributes => '{
          "instruction": "データベース内のテーブルを検索しユーザーの問い合わせ内容に関する情報を取得する",
          "tool_type": "SQL",
          "tool_params": {"profile_name": "NL2SQL_PROFILE"}}'
    );
END;
/

-- TASK作成 (SQL_TASK)
BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TASK(
        task_name => 'SQL_TASK',
        attributes => 
            '{
                "instruction": "ユーザからの質問: {query}。",
                "tools": ["SQL_TOOL"],
                "enable_human_tool": "False"
            }'
    );
END;
/

--Agent作成 (DB_SEARCH_AGENT)
BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
        agent_name => 'DB_SEARCH_AGENT',
        attributes => '{"profile_name": "NL2SQL_PROFILE",
           "role": "データベース内のテーブルからオーダー情報や在庫情報、顧客情報などのデータを取得する"
        }'
    );
END;
/

-- 動作確認用AgentTeam作成
BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TEAM(  
        team_name  => 'DB_SEARCH_TEAM',
        attributes => '{"agents": [
        {"name":"DB_SEARCH_AGENT","task":"SQL_TASK"}],
        "process": "sequential"
    }');
END;
/
-- 有効化
EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('DB_SEARCH_TEAM');

-- 動作確認
SQL> select ai agent ギガテンドーの注文件数を集計して。;

RESPONSE             
____________________ 
ギガテンドーの注文件数は18です。 

メール送信のタスクもSQL_TASKの結果を受け取れるようにinputを指定します。

試す場合の注意
後述しておりますが、ここで作成するTASKではうまく動作しません。正しい動作のためには「チューニング」の項にて紹介しているTASKとAGENTの作成が必要です。

Mailタスクの修正

-- TASKの作成
BEGIN
  -- 既存の削除
  BEGIN DBMS_CLOUD_AI_AGENT.DROP_TASK(task_name => 'Generate_Email_Task'); EXCEPTION WHEN OTHERS THEN NULL; END;

  DBMS_CLOUD_AI_AGENT.CREATE_TASK(
    task_name => 'Generate_Email_Task',
    attributes => '{
      "instruction": "指定されたアドレス宛に、日本語のメールを作成してください。",
      "tools" : ["EMAIL"],
      "enable_human_tool" : "false",
      "input": "SQL_TASK" 
    }'
  );
END;
/

利用するAgentとTASK

これらのAgentとTASKをチームにします。

  • SQL検索
    • Agent: DB_SEARCH_AGENT
    • Task: SQL_TASK
  • Mail送信
    • Agent: MAIL_AGENT
    • Task: Generate_Email_Task

Agent Teamの作成

それでは2つのAgentでAgentチームを作成します。

BEGIN
    DBMS_CLOUD_AI_AGENT.CREATE_TEAM(  
        team_name  => 'CUST_CONTACT_TEAM',
        attributes => '{"agents": [
        {"name":"DB_SEARCH_AGENT","task":"SQL_TASK"},
        {"name":"MAIL_AGENT","task":"Generate_Email_Task"}],
        "process": "sequential"
    }');
END;
/

検索内容の事前確認

Agentの回答のハルシネーションを判断できるように事前に検索内容の結果を確認しておきます。
ギガテンドーの注文数と内訳をAgent経由で取得しメール送信してもらいます。
実態は以下のように18件の注文があります。

-- ギガテンドーの注文数
SELECT 
    STATUS,
    COUNT(*) AS ORDER_COUNT,
    SUM(QTY) AS TOTAL_QTY
FROM 
    CUSTOMERS C
JOIN 
    ORDERS O ON C.CUST_ID = O.CUST_ID
WHERE 
    C.CUST_NAME = 'ギガテンドー'
GROUP BY 
    STATUS;

CUST_NAME       TOTAL_ORDERS    TOTAL_ORDER_QTY FIRST_ORDER_DATE    LAST_ORDER_DATE    
____________ _______________ __________________ ___________________ __________________ 
ギガテンドー                    18                170 13-FEB-26           11-MAR-26          

-- ギガテンドーの注文内訳
SELECT 
    O.ORD_DATE,         -- 注文日
    O.ORD_ID,           -- 注文番号
    O.PROD_ID,          -- 商品ID
    O.QTY,              -- 注文数量
    O.STATUS            -- ステータス(配送状況など)
FROM 
    CUSTOMERS C
JOIN 
    ORDERS O ON C.CUST_ID = O.CUST_ID
WHERE 
    C.CUST_NAME = 'ギガテンドー'
ORDER BY 
    O.ORD_DATE DESC;    -- 新しい注文順

ORD_DATE        ORD_ID PROD_ID       QTY STATUS       
____________ _________ __________ ______ ____________ 
11-MAR-26          691 MTR-016        17 Cancelled    
11-MAR-26          385 MTR-032        14 Pending      
10-MAR-26           53 SNS-021         7 Shipped      
09-MAR-26          876 CB-028          5 Cancelled    
08-MAR-26          229 CB-006         10 Cancelled    
05-MAR-26          333 MTR-015         6 Pending      
04-MAR-26          663 SNS-003         5 Pending      
02-MAR-26          796 CB-028         16 Pending      
27-FEB-26          176 MTR-026         3 Pending      
25-FEB-26          843 CB-007         20 Shipped      
24-FEB-26          977 CB-014          6 Shipped      
24-FEB-26          936 MTR-030        19 Shipped      
23-FEB-26          401 SNS-007         7 Shipped      
21-FEB-26          196 SNS-023         4 Shipped      
20-FEB-26          690 SNS-009         7 Cancelled    
19-FEB-26          200 SNS-024         1 Shipped      
13-FEB-26          810 CB-018          8 Shipped      
13-FEB-26          943 MTR-025        15 Pending      

18 rows selected. 

Agentへの依頼

Agentにデータの集計とメールの送信をお願いしてみます。

SQL> select ai agent ギガテンドーの注文件数を集計して、結果をxxx@gmail.comに送信して。;

RESPONSE                                                                                          
_________________________________________________________________________________________________ 
ギガテンドーの注文件数集計結果をxxx@gmail.comにメールで送信しました。総注文件数: 150件(内訳: 製品A: 50件、製品B: 60件、製品C: 40件)。

返事が返ってきましたが、集計結果が間違っています。

メールは送信できたか確認してみます。
image.png
送信はできていますが、やはり内容に間違いがあります。
添付ファイルがあると書いていますが、それもないですね。
少しチューニングが必要そうです。

チューニング

結果が0件となっていた原因として考えられる点は2つあります。

  1. DB_SEARCH_AGENTの結果取得不良
  2. DB_SEARCH_AGENTからMAIL_AGENTへの情報連携ミス

今回、単一のDB_SEARCH_AGENTの動作を確認した時には問題なく動作していたことから、2のデータ連携のミスの可能性が高いです。

そこでMAIL送信のTASKとAGENTの指令をより明確に記載するように修正します。

-- Generate_Email_Taskの修正
BEGIN
  -- 既存の削除
  BEGIN DBMS_CLOUD_AI_AGENT.DROP_TASK(task_name => 'Generate_Email_Task'); EXCEPTION WHEN OTHERS THEN NULL; END;

  DBMS_CLOUD_AI_AGENT.CREATE_TASK(
    task_name => 'Generate_Email_Task',
    attributes => '{
      "instruction": "前のタスクから受け取った検索結果の内容(注文件数など)を反映させて、日本語のメールを作成・送信してください。",
      "tools" : ["EMAIL"],
      "enable_human_tool" : "false",
      "input": "SQL_TASK" 
    }'
  );
END;
/

-- MAIL_AGENTの作成
BEGIN
  -- 既存のエージェントを削除
  BEGIN DBMS_CLOUD_AI_AGENT.DROP_AGENT(agent_name => 'MAIL_AGENT'); EXCEPTION WHEN OTHERS THEN NULL; END;

  DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
    agent_name => 'MAIL_AGENT',
    attributes => '{
      "profile_name": "MAIL_AGENT_PROFILE",
      "role": "あなたはメール送信の実行責任者です。1.前のタスク(SQL_TASK)から渡された「検索結果や集計数値」を正確に読み取ること。2.その内容に基づき、誠意のある日本語メール文面を作成すること。3.宛先はEMAILツールに設定されているものをそのまま使用し、勝手に捏造しないでください。",
      "tools": [
        {
          "tool_name": "EMAIL",
          "description": "メール送信ツール。前のタスクの結果得られた情報を本文に含めて送信してください。"
        }
      ]
    }'
  );
END;
/

-- Agent Teamの有効化
EXEC DBMS_CLOUD_AI_AGENT.SET_TEAM('CUST_CONTACT_TEAM');

再チャレンジ

今度はどうでしょうか確認してみましょう。

SQL> select ai agent ギガテンドーのオーダー情報を検索し注文件数を集計し、結果をxxx@gmail.comに送信してください。;

RESPONSE                                                                 
________________________________________________________________________ 
ギガテンドーのオーダー情報の集計結果(総注文件数: 18件)を反映したメールをxxx@gmail.comに送信しました。    

image.png
きちんと集計結果をメールで送ってくれています。

こんなプロンプトも試してみました。

SQL> select ai agent ギガテンドーのオーダー情報を検索しSTATUSPENDINGのものを一覧にしてください。その結果をxxx@gmail.comに送信してください ;

RESPONSE                                                                                                                                           
__________________________________________________________________________________________________________________________________________________ 
ギガテンドーのSTATUSPENDINGのオーダー情報一覧を、指定のメールアドレス(xxx@gmail.com)に送信しました。送信は成功しました。以下は送信した内容の概要です:                                                
                                                                                                                                                   
- ORDER_ID: 176, PRODUCT_ID: MTR-026, ORDER_STATUS: Pending, QUANTITY: 3, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-02-27, CUSTOMER_NAME: ギガテンドー     
- ORDER_ID: 333, PRODUCT_ID: MTR-015, ORDER_STATUS: Pending, QUANTITY: 6, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-03-05, CUSTOMER_NAME: ギガテンドー     
- ORDER_ID: 385, PRODUCT_ID: MTR-032, ORDER_STATUS: Pending, QUANTITY: 14, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-03-11, CUSTOMER_NAME: ギガテンドー    
- ORDER_ID: 663, PRODUCT_ID: SNS-003, ORDER_STATUS: Pending, QUANTITY: 5, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-03-04, CUSTOMER_NAME: ギガテンドー     
- ORDER_ID: 796, PRODUCT_ID: CB-028, ORDER_STATUS: Pending, QUANTITY: 16, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-03-02, CUSTOMER_NAME: ギガテンドー     
- ORDER_ID: 943, PRODUCT_ID: MTR-025, ORDER_STATUS: Pending, QUANTITY: 15, CUSTOMER_ID: CUST-006, ORDER_DATE: 2026-02-13, CUSTOMER_NAME: ギガテンドー    

こちらもきちんとメールが届きました!
image.png

まとめ

今回はADB内に作成したIn-Database AgentでDBの検索からメールの送信までを実施するエージェントチームを作成しました。
組み込み済みのツールで作成できるので非常に簡単に実装できました。実装自体は簡単ですが、正しく動作させるためにはAgentへの指令の書き方や粒度が非常に重要です。
AI Proxy Databaseで複数のデータソースを連携し、さらにデータの近くでAI Agentを動かすことで、散在したデータとAgentをまとめてシンプルに構成できて良いですね!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?