精通 Salesforce Einstein Bots:开发者视角下的 Apex 集成与自定义指南

背景与应用场景

在当今数字化的客户服务领域,企业面临着日益增长的客户查询量和对 24/7 实时响应的期望。传统的人工客服团队难以在成本可控的情况下满足这种需求。Salesforce Einstein Bots 作为 Salesforce Service Cloud 的一部分,提供了一个强大的人工智能(AI)驱动的聊天机器人解决方案。它旨在自动化处理重复性的客户咨询,从而解放人工坐席,让他们专注于处理更复杂、更具价值的客户问题。

对于 Salesforce 管理员和业务用户而言,Einstein Bots 提供了一个直观的、点击式的 Bot Builder 界面,可以快速构建常见的问答(FAQ)和简单的流程引导。然而,当业务需求超越了标准功能时——例如,需要与外部系统交互、执行复杂的业务逻辑、或对 Salesforce 内部数据进行复杂的增删改查操作——这便是 Salesforce 开发人员大显身手的舞台。

作为一名 Salesforce 开发人员 (Salesforce Developer),我们看待 Einstein Bots 的视角更为深入。它不仅仅是一个聊天工具,更是一个可扩展的自动化平台。通过集成 Apex,我们可以将 Bots 的能力从简单的对话流扩展到强大的后端业务流程执行器。常见的应用场景包括:

1. 动态数据查询与更新

客户可能想查询他们的订单状态、案例(Case)进度、或账户余额。这些信息是动态变化的,无法预先写死在对话中。通过调用 Apex,机器人可以接收用户提供的标识符(如订单号),实时查询 Salesforce 数据库或外部系统,并将最新信息返回给用户。

2. 复杂的记录创建与处理

当机器人收集到足够的信息来创建一个潜在客户(Lead)或案例(Case)时,可能需要执行超越标准“创建记录”元素的复杂逻辑。例如,根据输入的区域信息自动分配所有者、根据产品类别触发特定的验证规则、或在创建记录的同时更新相关的联系人信息。这些都可以封装在 Apex 方法中,确保数据的一致性和业务流程的正确性。

3. 与第三方系统集成

企业的业务生态系统往往涉及多个系统,如 ERP、物流系统、或支付网关。客户可能会询问“我的包裹到哪里了?”或“我的发票支付成功了吗?”。通过在 Apex 中发起 REST 或 SOAP API Callout,Einstein Bot 可以充当一个友好的前端,与这些外部系统通信,获取实时数据并呈现给用户,提供无缝的服务体验。

4. 高级身份验证与授权

在处理敏感信息之前,机器人需要验证用户身份。我们可以通过 Apex 调用 Salesforce 的身份验证服务或自定义的登录流程,实现安全的客户身份识别,然后再执行后续的敏感操作。


原理说明

Einstein Bots 与 Apex 的集成核心在于 Invocable Actions (可调用操作)。这是一个强大的 Salesforce 自动化特性,允许我们将一个 Apex 方法暴露给低代码/无代码工具,如 Flow Builder 和我们今天的主角——Einstein Bot Builder。

其工作流程如下:

1. 定义 Apex 类与方法: 我们需要创建一个全局(global)或公共(public)的 Apex 类。在这个类中,我们定义一个或多个静态(static)方法,并使用 @InvocableMethod 注解来标记它们。这个注解告诉 Salesforce 平台:“这个方法可以被机器人、流程等自动化工具调用。”

2. 定义输入输出结构: 为了在机器人和 Apex 之间传递数据,我们需要定义清晰的数据结构。通常的做法是在主 Apex 类中定义内部类(inner classes)。

  • 请求(Request)类: 用于封装从机器人传递到 Apex 的数据。这个类中的每个成员变量都用 @InvocableVariable 注解标记,代表一个输入参数。例如,机器人收集到的案例编号。
  • 响应(Response)类: 用于封装从 Apex 返回给机器人的数据。同样,这个类中的每个成员变量也用 @InvocableVariable 注解标记,代表一个输出参数。例如,Apex 查询到的案例状态和主题。

3. 在 Bot Builder 中调用 Apex: 在机器人的对话(Dialog)中,我们可以添加一个“操作(Action)”元素。在操作类型中选择“Apex”,此时,所有被 @InvocableMethod 注解标记的方法都会出现在可选项中。我们可以将机器人的变量(Variables)映射到 Apex 方法的输入参数,并将 Apex 的输出参数映射回机器人的变量。

4. 执行与返回: 当对话流执行到这个 Apex Action 步骤时,Salesforce 平台会实例化 Apex 类,并将机器人变量的值赋给请求类的实例。然后,它调用被注解的方法,执行其中的逻辑(如 SOQL 查询)。方法执行完毕后,将响应类实例中的值返回,并更新到机器人对应的变量中。机器人随后可以使用这些新获取的数据,继续与用户进行对话,例如,回复:“您好,您查询的案例状态是‘已解决’”。

这个机制的精妙之处在于,它将复杂的、需要编程实现的逻辑封装在一个黑盒(Apex 方法)中,同时为管理员或顾问提供了一个简单的、可配置的接口(Bot Builder 中的 Action 元素),实现了专业分工与高效协作。


示例代码

以下是一个非常经典的官方示例,用于根据用户提供的案例编号(Case Number)查询并返回该案例的状态(Status)和主题(Subject)。

Apex 类: CaseStatusBotAction

这个 Apex 类包含了一个可被机器人调用的方法,用于处理案例状态的查询逻辑。

/**
 * 这个 Apex 类为 Einstein Bot 提供了一个可调用的操作,
 * 用于根据给定的案例编号查询案例的状态和主题。
 */
public with sharing class CaseStatusBotAction {

    /**
     * @description 这是被 @InvocableMethod 注解标记的核心方法。
     *              它接收一个请求列表,并返回一个响应列表。
     *              Salesforce 自动化工具总是以列表形式批量处理数据。
     * @param requests 包含输入参数的请求对象列表。
     * @return 包含输出参数的响应对象列表。
     */
    @InvocableMethod(label='Get Case Status' description='Returns the status and subject of a case given a case number.')
    public static List<Response> getCaseStatus(List<Request> requests) {

        // 由于机器人通常一次只处理一个会话,所以我们主要关注列表中的第一个请求。
        // 但为了遵循最佳实践,代码应该能够处理多个请求。
        Request req = requests[0];

        // 准备一个列表来存放查询结果对应的响应。
        List<Response> responses = new List<Response>();
        // 准备一个列表来存放最终要返回给调用方的所有响应。
        List<List<Response>> allResponses = new List<List<Response>>();

        // 声明一个 Case 对象用于存放查询结果。
        Case caseRecord;

        try {
            // 使用 SOQL 查询与输入案例编号匹配的案例记录。
            // 使用 WITH SECURITY_ENFORCED 确保查询遵循当前用户的字段级安全。
            caseRecord = [SELECT Id, Status, Subject FROM Case WHERE CaseNumber = :req.caseNumber WITH SECURITY_ENFORCED LIMIT 1];

            // 创建一个新的响应对象。
            Response res = new Response();
            res.caseStatus = caseRecord.Status;
            res.caseSubject = caseRecord.Subject;
            res.isSuccess = true; // 标记操作成功

            // 将此响应对象添加到响应列表中。
            responses.add(res);

        } catch (Exception e) {
            // 如果查询失败(例如,找不到案例或发生其他错误),则构建一个错误响应。
            Response res = new Response();
            res.caseStatus = 'Not Found';
            res.caseSubject = 'Not Found';
            res.isSuccess = false; // 标记操作失败
            responses.add(res);
        }

        // 将本次调用的响应列表添加到总响应列表中。
        // 虽然这里只有一个请求,但 Invocable 方法需要返回 List> 吗?不,是 List
        // 官方文档的返回类型是 List, 所以这里 allResponses 变量不是必须的。直接返回 responses 即可。
        // 为了代码清晰和与文档一致,我们直接返回 responses。
        return responses;
    }

    /**
     * @description 内部类,定义了从机器人传递到 Apex 的输入参数。
     */
    public class Request {
        @InvocableVariable(label='Case Number' description='The number of the case to check.' required=true)
        public String caseNumber;
    }

    /**
     * @description 内部类,定义了从 Apex 返回到机器人的输出参数。
     */
    public class Response {
        @InvocableVariable(label='Case Status' description='The status of the case.')
        public String caseStatus;

        @InvocableVariable(label='Case Subject' description='The subject of the case.')
        public String caseSubject;

        @InvocableVariable(label='Is Success' description='True if the case was found, false otherwise.')
        public Boolean isSuccess;
    }
}

注意事项

1. 权限与安全 (Permissions & Security)

Einstein Bots 在运行时有其特定的用户上下文。在 Bot Builder 的“机器人设置”页面,您可以指定机器人的运行上下文用户。这个用户必须拥有:

  • 对被调用的 Apex 类的执行权限。
  • 对 Apex 代码中访问的所有对象(如 Case)和字段(如 Status, Subject)的读取或写入权限。
在编写 Apex 时,强烈建议使用 with sharing 关键字,以强制执行当前运行用户的共享规则。如果业务场景确实需要绕过共享规则,可以使用 without sharing,但必须极其谨慎,并确保不会意外泄露数据。使用 WITH SECURITY_ENFORCED 子句进行 SOQL 查询是强制执行字段和对象级安全性的现代最佳实践。

2. API 限制 (API Limits)

通过机器人调用的 Apex 代码与任何其他 Apex 事务一样,都受到 Salesforce 调控器限制 (Governor Limits) 的约束。这包括 SOQL 查询数量(100)、DML 语句数量(150)、总 CPU 时间等。虽然机器人对话通常是单线程的,每次调用只处理一个请求,但编写的 Apex 代码仍应遵循最佳实践,例如避免在循环中执行 SOQL 或 DML,以防止在复杂场景下触及限制。对于需要调用外部系统的场景,还要注意 Callout 的限制和超时时间(最长 120 秒)。

3. 错误处理 (Error Handling)

健壮的错误处理至关重要。如果 Apex 代码中发生未捕获的异常,机器人对话将中断,给用户带来糟糕的体验。

  • 使用 Try-Catch 块: 始终将核心逻辑包裹在 try-catch 块中。
  • 返回状态标志: 正如示例代码所示,包含一个布尔类型的输出变量(如 isSuccess)是一个非常好的实践。这允许机器人的对话流根据 Apex 执行是成功还是失败,走向不同的分支。
  • 提供友好提示: 如果 Apex 执行失败,机器人不应该直接显示技术性错误。管理员可以在 Bot Builder 中配置规则,检查 isSuccess 变量。如果为 false,机器人可以回复:“抱歉,我暂时无法查询到该信息,是否需要我为您转接人工客服?”

4. 部署与测试 (Deployment & Testing)

Invocable Apex 方法与其他 Apex 类一样,需要至少 75% 的代码覆盖率才能部署到生产环境。务必为您的 Invocable 方法编写全面的单元测试,覆盖成功路径、失败路径(如找不到记录)以及边界条件(如输入为空)。在 Bot Builder 中,您可以使用“预览”功能来测试集成了 Apex 的完整对话流。


总结与最佳实践

对于 Salesforce 开发人员来说,Einstein Bots 是一个令人兴奋的领域,它完美地连接了声明式配置和编程式自定义。通过掌握 Invocable Apex,我们可以极大地增强机器人的能力,使其从一个简单的问答工具转变为一个功能完备的自动化业务助理。

最佳实践总结:

  1. 单一职责原则: 让每个 Invocable 方法只做一件事情并把它做好。例如,一个方法用于查询状态,另一个用于创建记录。这使得方法更易于测试、维护和在不同的机器人或流程中重用。
  2. 明确的接口定义: 为您的 @InvocableMethod@InvocableVariable 提供清晰、易于理解的 labeldescription。这将极大地帮助配置机器人的管理员理解每个参数的用途。
  3. 批量化设计: 尽管机器人通常一次只发送一个请求,但 Invocable 方法的框架是为批量操作而设计的(输入和输出都是列表)。始终遵循这个模式编写代码,这将使您的代码未来也能够被其他批量工具(如 Flow)复用。
  4. 状态化沟通: 在 Apex 和机器人之间传递清晰的状态信息(如 isSuccess 标志和错误消息),而不仅仅是业务数据。这使得对话流可以做出智能的决策。
  5. 安全第一: 始终将安全放在首位。仔细考虑运行用户权限,并优先使用 with sharingWITH SECURITY_ENFORCED 来保护数据。

通过遵循这些原则和实践,我们可以构建出既强大又可靠的 Einstein Bots 解决方案,真正为企业提升客户服务效率,并创造卓越的客户体验。

评论

此博客中的热门博文

Salesforce 登录取证:深入解析用户访问监控与安全

Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)

Salesforce Einstein AI 编程实践:开发者视角下的智能预测