Agentforceの真髄を探る

みなさんこんにちは。エンジニアの佐藤です。今回は、最近筆者が講演した社内セミナーの中で好評だった「Atlas推論エンジン Deep Dive」の内容からお話しさせてください。

AgentforceとAtlas推論エンジン

生成AI、特に大規模言語モデル(LLM)が人間のような思考・判断をして、会話の返答などのさまざまなタスクを実行する様子は、見事というほかありません。AgentforceにはこのLLMが高度に統合されており、魔法のような機能が本当にわずかな手順で実装できてしまいます。

しかし、理解が難しかったポイントもあります。多くの人にとって、具体的な戸惑いポイントはAgentforceのエージェント作成における「トピックとアクション」の配置でしょう。エージェントとトピックを紐づけるポインタやリファレンスというものはありません。同様にトピックの中のアクションがどうやって選択されるかを事前に設定することはできません。代わりにあるのは、トピックの「分類の説明」や「エージェントアクション手順」などと言った自然言語表現、いわば「お品書き」だけです。

Agentforceの実行系の中で、これらのお品書きの選択を司る部分は「Atlas推論エンジン」と呼ばれています。SalesforceはAtlas推論エンジンについて、以下のようにいくつかのブログを公開しています。

しかし、これらは具体的な実装については何も情報提供していません。企業秘密なのでしょうが、もう少し具体的な情報が欲しいところです。そんな折、その具体的な舞台裏を少しだけ覗く方法があることを、同僚Tさんから教えてもらいました。

以下に、筆者が確認した一部を紹介させていただきます。なお、本ブログの調査結果は、執筆時点のSalesforce開発者組織に関するものであり、製品アップデートで変化する可能性があることにご注意ください。操作手順は執筆時点の開発者エディションで確認したものです。

準備作業

Salesforceは、LLMによるテキスト生成の過程を細かくエクスポートする機能を備えています。エクスポート結果はData CloudのいくつかのDLOに分けて保存されます。DLO間の結合条件は公式ヘルプに書かれています。

このエクスポートを有効にするためには、以下の操作を行います。

[Data Cloud設定]

  1. Data Cloud 設定ホーム
    • Data Cloud を設定=> 「Get Started」(あるいは日本語の相当メッセージ)をクリックして、しばらく待つ。

[設定]

  1. Einstein > Einstein 生成 AI > Einstein 設定
    • Einstein を有効化 => ONに設定
  2. Einstein > Einstein 生成 AI > Einstein フィードバックおよび監視の設定
    • フィードバック => ONに設定
  3. Einstein > Einstein 生成 AI > エージェントスタジオ > エージェント
    • Agentforce (Default) を有効にしてビルダーで開く
    • あらかじめ設定してあるトピックをすべて削除

検証用トピックとアクションの設定

今回は検証用に以下のようなトピックを追加しました。

四則演算

分類の説明:
      ユーザーからの四則演算に関する質問に対応します。加算、減算、乗算、除算の計算を行います。
      以下のアクションを使って計算してください。
      - 2つの数値を加算
      - 2つの数値を減算
      - 2つの数値を乗算
      - 2つの数値を除算

アクションには以下のようなApexコードを設定しました。(代表例のみ)

public class AddTwoNumbersAction {
    public class Input {
        @InvocableVariable(label='最初の数値' description='加算する最初の数値' required=true)
        public Decimal number1;

        @InvocableVariable(label='2番目の数値' description='加算する2番目の数値' required=true)
        public Decimal number2;
    }

    public class Output {
        @InvocableVariable(label='合計' description='加算結果')
        public Decimal result;
    }

    @InvocableMethod(label='2つの数値を加算' description='2つの数値を加算して結果を返します')
    public static List<Output> add(List<Input> inputs) {
        List<Output> results = new List<Output>();
        for (Input input : inputs) {
            Output output = new Output();
            output.result = input.number1 + input.number2;
            results.add(output);
        }
        return results;
    }
}

大文字小文字の変換

分類の説明:
    ユーザーがテキストの大文字小文字を変換するためのリクエストを処理します。
    処理には以下のアクションを使用してください。
    - 文字列を大文字に変換
    - 文字列を小文字に変換

同様に、アクションには以下のようなApexコードを設定しました。(代表例のみ)

public class ToLowerCaseAction {
    public class Input {
        @InvocableVariable(label='変換対象の文字列' description='小文字に変換する文字列を指定してください' required=true)
        public String originalString;
    }

    public class Output {
        @InvocableVariable(label='小文字変換後の文字列' description='小文字に変換された結果の文字列')
        public String resultString;
    }

    @InvocableMethod(label='文字列を小文字に変換' description='指定された文字列を小文字に変換します')
    public static List<Output> convert(List<Input> inputs) {
        List<Output> results = new List<Output>();
        for (Input input : inputs) {
            Output output = new Output();
            output.resultString = (input.originalString != null) ? input.originalString.toLowerCase() : null;
            results.add(output);
        }
        return results;
    }
}

なお、「分類の説明」以外の項目は、すべて自動生成された文言のまま使用しています。

動作確認

トピックをアクションを設定したら、今開いているエージェントビルダーの「会話プレビュー」に以下のように入力し、送信します。

1+1を計算してください。

すると、トピック「四則演算」の加算アクションが選択され、以下のように出力されます。

計算結果は次のとおりです。
2

質問を以下のように変えても動作は同じで、トピック「四則演算」の加算アクションが選択され、以下のように出力されます。

1と1を足してください。
1と1を足した結果です。
2

これは、まぁ、当たり前の、期待通りの動作と言えるでしょう。しかし、以下のような疑問が湧いてきませんか?

  • 四則演算のトピックが選択されたのは、なぜか?他が選択されなかったのはなぜか?
  • 加算アクションが選択されたのは、なぜか?他が選択されなかったのはなぜか?

いったいどのような仕掛けが、Apexクラス AddTwoNumbersAction の add メソッドへと処理を導いたのでしょうか?

「フィードバック」を覗く

ここでData Cloudのクエリーエディターを開いて以下のようなクエリを実行してみましょう。(UTC時刻は適宜調整してください。)

SELECT 
    R.prompt__c,
    G.responseText__c,
FROM GenAIGatewayRequest__dll R
LEFT JOIN GenAIGatewayResponse__dll S 
    ON R.gatewayRequestId__c = S.generationRequestId__c
LEFT JOIN GenAIGeneration__dll G
    ON S.generationResponseId__c = G.generationResponseId__c
WHERE R.timestamp__c >= timestamp '2025-06-02 10:00:00'
    AND R.timestamp__c < timestamp '2025-06-02 20:00:00'
ORDER BY R.timestamp__c ASC

なお、 prompt__c と responseText__c にはとても長いテキストデータが設定されるため、Data Cloudのクエリーエディターでの観察は困難です。以下のようにSalesforce CDP Connectorを用いてテキストファイルにします。

from salesforcecdpconnector.connection import SalesforceCDPConnection

with open('./private_key.pem') as fd:
    your_key = fd.read()

conn = SalesforceCDPConnection("https://login.salesforce.com", client_id=..., username=..., private_key=your_key)

query = (クエリ文面)
df = conn.get_pandas_dataframe(query)

def row_serializer(r):
    return f"REQUEST {'>'*73}\n{r['requestTimestamp']}\n{'>'*80}\n{r['prompt__c']}\n" + f"RESPONSE {'<'*72}\n{r['responseTimestamp']}\n{'<'*80}\n{r['responseText__c']}\n"

with open("2025-06-02_02.txt", "wt") as f:
    out = "\n".join(df.apply(row_serializer, axis=1))
    f.write(out)

興味深い出力結果

こうして出力したテキストファイルには、非常に興味深い情報が含まれています。

例えば以下です(一部を省略しています)。

REQUEST >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2025-06-02 10:46:44.614000+00:00
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
topics:
arithmetic_calculation: ユーザーからの四則演算に関する質問に対応します。加算、減算、乗算、除算の計算を行います。
以下のアクションを使って計算してください。
- 2つの数値を加算
- 2つの数値を減算
- 2つの数値を乗算
- 2つの数値を除算
tpc_03618d78_2b1f_ebae_a88f_4d7a97e6ad3f: ユーザーがテキストの大文字小文字を変換するためのリクエストを処理します。
処理には以下のアクションを使用してください。
- 文字列を大文字に変換
- 文字列を小文字に変換

role: user
1+1を計算してください。
role: system
Now, based on the available topics defined in the system message and the conversation history, output only the single topic name:
RESPONSE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2025-06-02 10:46:44.614000+00:00
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
arithmetic_calculation

読むとわかるとおり、これはトピックを選択するためのプロンプトです。role:user の次の行は「1+1を計算してください。」という、入力質問文面そのものが展開されています。topics:の部分には、エージェントビルダーにおけるトピック「四則演算」の「分類の説明」文面がそのまま展開されています。そして最後は、素直にトピックのAPI名の選択を求め、レスポンスは「arithmetic_calculation」となっています。

これがAtlas推論エンジンの「推論」の一端であることは明らかです。結局、LLMに素直に相談していた、ということです。

試しにこのプロンプトをAzure AI FoundryのGPT-4o入力すると、全く同じ返信が返されます。

続いている以下の出力結果は、アクションの選択がどのように行われているかを強く示唆するものです(一部を省略しています)。

REQUEST >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2025-06-02 10:46:45.118000+00:00
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
topic: arithmetic_calculation
job: 私の仕事は、ユーザーからの四則演算の質問に対して正確に計算結果を提供することです。
instructions:
- 必要に応じて、ユーザーに追加の情報を尋ねます。
- 計算結果をユーザーに提供します。
- 計算に誤りがないか確認します。
- ユーザーからの質問を受け取ったら、四則演算の種類を特定します。

function_outputs:
- SubtractTwoNumbersAction:
    result (lightning__numberType): 減算結果
- AddTwoNumbersAction:
    result (lightning__numberType): 加算結果
- MultiplyTwoNumbersAction:
    result (lightning__numberType): 乗算結果
- DivideTwoNumbersAction:
    result (lightning__numberType): 除算結果(除数が0の場合はnull)

role: user
1+1を計算してください。
RESPONSE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2025-06-02 10:46:45.118000+00:00
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

instructions:に並んでいるのは、トピック「四則演算」に設定されている「手順」の文面そのものです。この出力結果には収録されていませんが、実際にはこの後に、トピックに設定されたアクションの紹介が続いていることは、Open AIのAPI仕様からも容易に想像できます。アクション選択も最終的にはこのようにLLMに相談して決めているようです。

明瞭化で限界がわかる

本調査によって、Atlas推論エンジンの処理の一端を覗くことができました。実際にはもっとさまざまな処理をしているのでしょうが、「トピック選択」と「アクション選択」という、開発技術者にとって重要な2つについて、重要な知見が得られたと思います。

今回紹介したプロンプトはまた、実際のエージェント開発において目的動作が得られなかった場合の調整方針についても参考になると思います。

最後までお読みいただきありがとうございました。