게시일: 2026년 6월 12일 | 읽는 시간: 7분 | 카테고리: Salesforce
요약
Agentforce Service Agent를 사용하여 리드를 캡처하려면 다중 턴 상태 관리를 안전하게 처리해야 합니다. 표준 플로(Flow)는 간단한 작업에 유용하지만, Apex @InvocableMethod를 사용하면 대화 턴 전반에 걸쳐 지속적인 상태 추적과 안전한 USER_MODE DML 작업을 수행할 수 있습니다. 구축 방법은 다음과 같습니다.
소개: Agentforce 시대
Salesforce Agentforce는 자동화된 고객 상호 작용에 대한 우리의 생각을 완전히 바꾸어 놓았습니다. 우리는 엄격한 트리 기반 챗봇에서 추론하고, 명확한 질문을 하고, 작업을 실행할 수 있는 자율 에이전트로 나아가고 있습니다.
Agentforce의 가장 일반적인 초기 사용 사례 중 하나는 리드 캡처입니다. 목표는 간단합니다. AI 에이전트가 사용자에게 정보(예: 성 및 회사)를 요청하고, 여러 대화 턴에 걸쳐 해당 정보를 보유하며, 필요한 모든 데이터가 수집되면 Salesforce 리드 레코드를 생성하는 것입니다.
화면 플로(Screen Flow)나 자동 실행 플로(Autolaunched Flow)로 이를 시도할 수도 있지만, **Apex 호출 가능 작업(Apex invocable actions)**은 상태 관리 및 보안 컨텍스트에 대한 훨씬 더 많은 제어를 제공합니다.
프로덕션 준비가 된 2026년 리드 캡처 에이전트에 대한 정확한 청사진은 다음과 같습니다.
아키텍처
이 솔루션에는 세 가지 핵심 구성 요소가 필요합니다.
- 에이전트 라우터 (
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이 언제 리드를 생성해야 하는지 추측하게 하는 대신, 호출 가능 작업을 사용하여 비즈니스 로직을 안전하게 관리합니다.
플로(Flow) 대신 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의 중요한 미묘한 차이입니다. 호출 가능 작업의 출력을 Agent Script 변수(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을 적용하며, 에이전트 사용자에게 올바른 권한 집합을 할당하는 것을 잊지 마세요.
저자 정보: 이 가이드는 Resumity 기술 편집 팀에서 작성했으며, 최신 AI 플랫폼과 엔터프라이즈 CRM 아키텍처의 교차점을 탐구합니다.