公開日: 2026年6月12日 | 読了時間: 7分 | カテゴリ: Salesforce
TL;DR
Agentforceサービスエージェントを構築してリードをキャプチャするには、マルチターンの状態管理を安全に処理する必要があります。標準のフローは単純なタスクには適していますが、Apexの@InvocableMethodを使用すると、会話のターン全体で永続的な状態追跡と安全なUSER_MODE DML操作が可能になります。以下に、その構築方法を正確に示します。
はじめに:Agentforce時代
Salesforce Agentforceは、自動化された顧客インタラクションの考え方を完全に変えました。私たちは、固定的なツリーベースのチャットボットから、推論し、明確化のための質問をし、アクションを実行できる自律エージェントへと移行しています。
Agentforceの最も一般的な初期ユースケースの1つはリードキャプチャです。目標はシンプルです。AIエージェントがユーザーに必要な情報(例:姓と会社)を尋ね、その情報を複数の会話のターンにわたって保持し、必要なデータがすべて収集されたらSalesforceリードレコードを作成します。
画面フローや自動起動フローでこれを試すこともできますが、Apexインボカブルアクションは、状態管理とセキュリティコンテキストに対してはるかに優れた制御を提供します。
ここでは、2026年の本番環境に対応したリードキャプチャエージェントの正確なブループリントを示します。
アーキテクチャ
このソリューションには、3つのコアコンポーネントが必要です。
- エージェントルーター (
start_agent): ユーザーを歓迎し、インテントに基づいて適切なサブエージェントにルーティングします。 - リードキャプチャサブエージェント (
subagent): LLMにどのフィールドが必要か(姓と会社)を正確に指示し、アクションをトリガーします。 - Apexインボカブルアクション (
@InvocableMethod): 入力を解析し、状態を保持し、データベース挿入を実行する実際の「エンジン」です。
1. エージェントスクリプトDSL
Agentforceは、エージェントの動作を定義するために特定のドメイン固有言語(DSL)を使用します。ターンをまたいでユーザーの入力を保持するための変数を定義します。
variables:
last_name: mutable string = ""
description: "Lead last name"
company: mutable string = ""
description: "Lead company"
lead_created: mutable boolean = False
description: "Whether the lead has already been created"
last_lead_id: mutable string = ""
description: "The most recently created Lead ID"
サブエージェントのロジックは、ユーザーがリードキャプチャトピック中に送信するすべてのメッセージに対して、Apexアクションを呼び出すことを指示します。現在のuserMessageと、これまでに収集したlast_nameおよびcompany変数を渡します。
subagent lead_capture:
label: "Lead Capture"
description: "Collect last name and company, then create a Salesforce Lead through Apex."
reasoning:
instructions: ->
if @variables.lead_created == True:
| A lead has already been created in this conversation. Share the Lead ID and ask if the user wants anything else.
if @variables.lead_created == False:
| Use Process Lead Capture Turn for every lead-capture message.
actions:
process_lead_turn: @actions.process_lead_turn
with userMessage = ...
with knownLastName = @variables.last_name
with knownCompany = @variables.company
set @variables.last_name = @outputs.resolvedLastName
set @variables.company = @outputs.resolvedCompany
set @variables.lead_created = @outputs.isSuccess
set @variables.last_lead_id = @outputs.leadId
2. Apexインボカブルアクション
このパターンの真の力は、Apexクラスにあります。LLMにリードを作成するタイミングを推測させるのではなく、インボカブルアクションを使用してビジネスロジックを安全に管理します。
フローではなくApexを使用する理由
- マルチターンの状態:
knownLastNameとknownCompanyをApexアクションに渡し、resolvedLastNameとresolvedCompanyを返すことで、ユーザーが情報を順不同で提供した場合でも、会話の状態を完全に維持できます。 - セキュリティコンテキスト:
AccessLevel.USER_MODEを使用して、フィールドレベルセキュリティ(FLS)とCRUD権限を動的に強制できます。
以下は、入力および出力変数の構造です。
public class LeadCaptureTurnAction {
public class Request {
@InvocableVariable(required=true label='User Message')
public String userMessage;
@InvocableVariable(label='Known Last Name')
public String knownLastName;
@InvocableVariable(label='Known Company')
public String knownCompany;
}
public class Result {
@InvocableVariable(label='Is Success')
public Boolean isSuccess;
@InvocableVariable(label='Lead ID')
public String leadId; // GOTCHA: Must be String, not Id
@InvocableVariable(label='Resolved Last Name')
public String resolvedLastName;
@InvocableVariable(label='Resolved Company')
public String resolvedCompany;
@InvocableVariable(label='Message')
public String message;
}
@InvocableMethod(label='Process Lead Capture Turn')
public static List<Result> processTurn(List<Request> requests) {
// 1. Parse the userMessage for missing fields using Regex
// 2. Combine found fields with knownLastName and knownCompany
// 3. If both are present, insert the Lead
// 4. Return the Result
}
}
leadIdバインディングの注意点
public String leadId;がIdではなくStringとして定義されていることに注意してください。これはAgentforceにおける重要な。。。ュアンスです。インボカブルアクションの出力をエージェントスクリプト変数にバインドする際(set @variables.last_lead_id = @outputs.leadId)、Agentforceは厳密なSalesforceのId型よりもプリミティブな文字列型を強く推奨します。Idを使用すると、実行中にサイレントバインディングエラーが発生する可能性があります。
3. USER_MODEを使用したセキュリティの強制
Agentforceがインボカブルアクションを実行すると、Einstein Service Agentユーザー(または設定されたデフォルトのエージェントユーザー)のコンテキストで実行されます。
標準DML(insert newLead;)を使用してリードを挿入しようとすると、システムコンテキストが必要なセキュリティチェックをバイパスしたり、組織の共有設定によっては予期せず失敗したりする可能性があります。
2026年の正しいアプローチは、常にユーザーモードDMLを強制することです。
Database.SaveResult sr = Database.insert(newLead, false, AccessLevel.USER_MODE);
不足している権限セット
USER_MODE挿入を機能させるには、Einstein Service Agentユーザーがリードレコードを作成する権限を持っている必要があります。
権限セット(例:LeadCaptureAgent_Apex_Access)を作成し、以下を付与する必要があります。
- Apexクラスアクセス:
LeadCaptureTurnActionクラスへのアクセス。 - オブジェクトアクセス:
Leadオブジェクトに対する読み取りおよび作成権限。 - フィールド権限:
LastNameおよびCompanyフィールドに対する編集アクセス。
この権限セットをEinstein Service Agentユーザーに割り当てます。これがないと、エージェントはサイレントUSER_MODE DML失敗によりisSuccessがtrueを返すことができないため、すでに収集したフィールドを要求し続けてループします。
4. エージェントのローカルテスト
公開する前に、Salesforce CLIを使用してマルチターンのロジックを検証する必要があります。sf agent previewコマンドを使用すると、ターミナルから直接会話をシミュレートできます。
# Start the session
sf agent preview start --json --authoring-bundle LeadCaptureAgent --use-live-actions --target-org my-org
# Send the first utterance (Company only)
sf agent preview send --json --session-id <SESSION_ID> --utterance "My company is Acme Corp" --authoring-bundle LeadCaptureAgent --target-org my-org
# Send the second utterance (Last Name)
sf agent preview send --json --session-id <SESSION_ID> --utterance "My last name is Smith" --authoring-bundle LeadCaptureAgent --target-org my-org
# Verify the Lead creation
sf data query --query "SELECT Id, LastName, Company FROM Lead ORDER BY CreatedDate DESC LIMIT 1" --target-org my-org
結論
Agentforceは、信じられないほどダイナミックな会話体験を構築することを可能にしますが、状態とセキュリティの処理方法のシフトが必要です。リードキャプチャを専用のサブエージェントにルーティングし、決定論的な状態管理のためにApexインボカブルアクションに依存することで、安全で回復力があり、ユーザーフレンドリーなエクスペリエンスを保証します。
ID出力には常にStringを使用し、USER_MODE DMLを強制し、エージェントユーザーに適切な権限セットを割り当てることを忘れないでください。
著者について: このガイドは、最新のAIプラットフォームとエンタープライズCRMアーキテクチャの交差を探求するResumityテクニカルエディトリアルチームによって作成されました。