让 AI 智能体运行 Apex 测试:Salesforce 的 MCP
Nimbus 在 2026 年 10 月改名为 renmy runtime:同一个工具,同一个二进制文件。改名的记录在这里。
简而言之。 AI 编程智能体(agent)在 Python 和 TypeScript 上表现很好,因为它们能运行自己写的代码,并在一秒内读到结果,一个任务里能这样来回几十次。但换成 Salesforce Apex,它们就卡住了,因为 Apex 唯一能运行的地方是 Salesforce org,隔着网络,一次要等上几分钟。
renmy runtime 是一个本地 Salesforce Apex 运行时:它在你自己的机器上执行真正的 Apex、SOQL、DML 和 Salesforce Flows,底层用内嵌的 PostgreSQL,不需要 org、不需要 scratch org、不需要 sandbox、不需要 Docker,也不需要 JVM。它的 renmy mcp 命令是一个 MCP 服务器,为 Claude Code、Cursor、GitHub Copilot 以及任何 MCP 客户端提供 run_apex_tests、explain_failure 这类工具,于是智能体也能拿到它在别处惯用的「写—跑—改」循环,而 org 只会看到已经通过测试的代码。部署仍然要过 renmy deploy 这道关。
为什么编程智能体在 TypeScript 里跑得动,在 Apex 上却卡住
AI 编程智能体本质上是一个循环:写一处改动,运行点东西,读回结果,决定下一步做什么。在 TypeScript 或 Python 项目里,「运行点东西」意味着在本机启动一个进程:npm test、pytest、一个临时脚本。一两秒就能返回,还带一段智能体能读懂的堆栈信息。一个任务里,智能体会把这个循环走二十到四十遍,最后交出来的是它亲眼看着跑通的代码。
Salesforce Apex 恰恰在「运行点东西」这一步把循环打断了。Apex 只能在 Salesforce org 内部编译和执行:编译器、数据库和测试运行器都在 Salesforce 的数据中心,不在开发者机器上。要跑一个测试,智能体得先把类部署到 org,等待,启动测试,轮询直到结束,然后抓取并解析调试日志。每个循环要几分钟,而且智能体还得持有 org 的凭证。
公开的测量数据是这样的:四个开源 Apex 测试套件、837 个测试,在 Salesforce org 里部署加运行大约要 1 分 46 秒(方法和数据)。智能体的反应无非两种,而两种都不妙。
有些 agent 就此打住:把类和测试写出来,描述测试“本该”检查什么,然后把没人跑过的代码交回去。另一些则硬着头皮往下走,每一轮反复都要耗掉几分钟和一肚子 token。两种做法都绕不开同一个问题:agent 最擅长的事,也就是不知疲倦又低成本地反复验证,恰恰是 Apex 从它手里拿走的东西。本地 Apex 运行时改变的正是这一点。renmy runtime 是本地的一套 Salesforce Apex 运行时和开发工具链,能在开发者的机器上,对着一个内嵌的 PostgreSQL,执行真正的 Apex(类、接口、枚举、泛型、触发器)、SOQL 和 DML,以及 Salesforce Flow(自动启动型、记录触发型、屏幕型)。不需要 Salesforce 组织,不需要临时组织,不需要沙箱,不需要 Docker,也不需要 JVM:macOS、Linux 和 Windows 上各一个二进制文件。它不是 mock,也不是把 Apex 转译成 Java 的转译器。Governor 限制会照常执行;Test.startTest / Test.stopTest、@testSetup、每个测试的事务隔离、Stub API,以及触发器和 Flow 的 execution order,表现都和平台上一致,而且对等性记录是公开的。一个典型的 Apex 测试连同 SOQL 和 DML 在内,几十毫秒就能跑完。前面那个 837 个测试的基准,在本地 2.4 秒跑完,大约快 45 倍,而且每个测试在本地和平台上都通过。对 Java 开发者来说,这就是他们笔记本上一直有的那个 JVM。对 AI agent 来说,这是循环里缺失的那一半。如果本地运行时对你还很陌生,《What a local runtime is, and why Salesforce never gave you one》会从零讲起,《renmy runtime explained》则会把整套工具链走一遍。
renmy mcp 提供给 agent 的能力
Model Context Protocol(MCP)是编码 agent 调用工具的方式。一个 server 描述一组函数,每个函数带类型化的输入;客户端也就是 agent,通过 JSON-RPC 调用它们,读回结构化的结果。renmy mcp 就是这样一个 server。它作为 agent 的子进程运行,通过 stdio 通信,所以没有端口、没有网络、也没有凭据。agent 能碰到的,就是它眼前磁盘上的这个项目,别的都碰不到。这些工具就是运行时自己的命令,背后是同一个引擎:
run_apex_tests:跑一个类、一个方法,或者像*这样的模式,把结果作为数据拿回来,而不是拿回一份要自己解析的日志。
explain_failure:完整还原一次失败。包括异常、出错的源码位置、预期值与实际值、失败前刚执行过的 SOQL 和 DML,以及引擎无法确定的部分。它和 renmy explain 打印的内容是同一份数据。
get_coverage:本次运行的语句覆盖率和分支覆盖率。
get_execution_trace:本次运行的执行轨迹,即哪些代码被执行、按什么顺序执行。
execute_anonymous:在本地数据库上跑一段 Apex 代码,相当于给智能体一个 REPL。
list_test_classes:在写新测试之前,先看看哪些代码已经有测试了。
完整列表见 CLI 参考文档。
MCP 服务器属于 Pro 功能,公测期间免费。如果智能体能执行 shell 命令(Claude Code 就是如此),那么用 Free 版的 renmy test 和 renmy explain 就能跑通大部分流程;MCP 服务器只是把同样的结果以结构化数据返回,而不是终端输出。
如何把 Claude Code、Cursor 或 Copilot 接到 renmy runtime
# 安装 runtime
curl -fsSL https://renmy.net/install.sh | sh # macOS、Linux
irm https://renmy.net/install.ps1 | iex # Windows PowerShell
cd your-sfdx-project
先把最后那条命令自己跑一遍,再把项目交给 agent。这样你就知道测试套件在本地能跑通,也清楚它要跑多久。第一次运行的详细步骤都在 quickstart 里。
注册 MCP 服务器
# Registers renmy mcp with the agent clients on this machine
renmy mcp install
# Or in Claude Code directly. The server's registered name is nimbus.
claude mcp add nimbus -- renmy mcp
Cursor 读取项目里的 .cursor/mcp.json,配置项和上面是同一条命令:
{
"mcpServers": {
"nimbus": {
"command": "renmy",
"args": ["mcp"]
}
}
}
GitHub Copilot 的 agent 模式和其他 MCP 客户端都用同样的 stdio 命令:renmy mcp。注册名一直是 nimbus,即使项目改过名也没变,所以 2026 年 10 月之前配好的 agent 还能照常工作。
操作指南《Let AI agents run Apex tests》逐个客户端走了一遍配置流程,还介绍了 renmy skills——面向常见 Salesforce 任务整理好的 agent 工作流。
本地 Apex 运行时下的 agent 会话是什么样
假设你对 Claude Code 说:"超过 1 万的发票打 95 折。加到 InvoiceService 里,并写测试。"
循环过程如下,工具调用名称也标出来:
list_test_classes 找到 InvoiceServiceTest。agent 读取这个类和对应的服务类,然后写出方法和测试:
@IsTest
static void appliesFivePerCentAboveThreshold() {
Invoice__c inv = new Invoice__c(Amount__c = 12000);
insert inv;
Test.startTest();
InvoiceService.applyDiscounts(new List<Id>{inv.Id});
Test.stopTest();
inv = [SELECT Discount__c FROM Invoice__c WHERE Id = :inv.Id];
Assert.areEqual(600, inv.Discount__c);
}
run_apex_tests 在 InvoiceServiceTest 上运行。出现一个失败,用时远不到一秒。explain_failure 分析那个方法。预期是 600,实际是 0;断言前的 SOQL 和 DML 显示,服务查了发票但没执行更新:它的查询过滤了一个测试从未设置的状态。agent 修复了过滤条件。再跑 run_apex_tests。通过。get_coverage 显示该类的分支覆盖率,标出了正好在 1 万这个边界上未被测试的路径,于是 agent 补了一个边界测试。用 "*" 运行 run_apex_tests。整个测试套件,几秒钟跑完。
改动了 InvoiceService,现在就能发现它破坏了别处的某个触发器测试,而不是等到 org 里才暴露。每轮只要几秒。因为几乎不花时间,智能体每次编辑后都把整套测试跑一遍,这个习惯大多数人到第三轮就丢了。整个过程中没有动过任何 org。你审查的是一个 diff 和一次测试运行,而且都能在自己的终端里复现:renmy test InvoiceServiceTest
renmy explain InvoiceServiceTest.appliesFivePerCentAboveThreshold
Agentforce、Headless 360,以及 MCP 工具背后的 Apex
这里还有第二个 MCP。Salesforce Headless 360(2026 年 4 月)允许团队在 Salesforce 里配置自定义 MCP 服务器,把已有的 Apex 钩子包装成工具。@InvocableMethod、@AuraEnabled、@RestResource 和自动启动的 Flow 都能变成工具,交给 Agentforce 代理或外部代理在生产环境调用。这些钩子本质上就是普通的 Apex 和 Flow 元数据,而 renmy 运行时已经能在本地执行所有这些内容。因此,Headless 360 工具背后的代码可以离线测试,跑在嵌入式 PostgreSQL 上,不需要额外配置。renmy 运行时如何与 Headless 360 对接,文档里有详细说明。
代理该在哪里止步:部署
本地测试通过是必要条件,但不是充分条件。组织里有权限集、托管包、验证规则,还有其他团队的自动化,这些东西你的仓库里并不包含。一致性记录之所以公开,正是因为它并非 100% 一致。所以代理不该自行部署,划定这条边界的工具是 renmy deploy。它把部署内容快照成一个包,针对这个包运行本地测试和覆盖率门禁,再用真实的 Salesforce check-only 验证在目标 org 里校验完全相同的字节,只有这些都通过才会真正部署。这个命令在免费版里就能用。
renmy release validate 和 renmy release deploy(属于 Pro 版,测试期免费)把部署拆成两半,中间附带一份不可篡改的回执,记录包摘要、Git 版本、org 指纹、门禁结果、Salesforce 验证任务 ID 和快速部署有效期。这样人类可以在两步之间做审批。让代理去跑测试;部署,或者至少审批这一步,留在人手里。Deploy 和 Release 两篇文档分别介绍了这两个命令。
留在 org 里的东西没有变:UI、集成、最终验证。而在那之前的一百次修改,都发生在运行时里。
适合谁
在 Salesforce 代码库上使用 Claude Code、Cursor 或 GitHub Copilot 的开发者,尤其是那些眼看着代理生成 Apex、却从没运行过的人。
构建 Agentforce 或 Headless 360 工具的团队,希望工具背后的 Apex 在进入 org 之前就先经过测试。
让你的 AI agent 运行 Apex 测试:面向 Salesforce 的 MCP
如果你负责 AI 工具,又需要回答“我们的 agent 能在 Salesforce 上干活吗”——与其做一页幻灯片,不如直接演示。上手试试:
curl -fsSL https://renmy.net/install.sh | sh
cd your-sfdx-project
renmy test "*"
renmy mcp install
上手只要五分钟。集成方式可以参考 AI 与 agentic 编码页面。问题反馈、文档、示例和已发布的二进制文件都在 github.com/renmy-solutions/renmy;疑问可以到 Slack 提问。
常见问题
AI agent 需要有 Salesforce org 才能用 renmy runtime 跑 Apex 测试吗?
不需要。renmy runtime 直接在开发者本机运行,对内置的 PostgreSQL 执行 Apex、SOQL、DML 和 Salesforce Flows。renmy mcp 服务器作为 agent 的子进程通过 stdio 运行,不需要 org、不需要凭证、不需要网络,也不占端口。只有部署时才会涉及 org。
哪些 AI 编码 agent 能配合 renmy mcp 使用?
任何 MCP 客户端都行。Claude Code 用 claude mcp add nimbus -- renmy mcp 注册;Cursor 通过它的 mcp.json 注册;GitHub Copilot 的 agent 模式和其他客户端也使用同样的 stdio 命令 renmy mcp。renmy mcp install 会替你完成注册。注册后的名字是 nimbus。
renmy mcp 免费吗?
MCP 服务器属于 Pro 套餐,公测期间免费;公测结束后标价为每月 19 美元。Free 套餐 0 美元、无需绑卡,包含不限次数的本地测试运行,所以只要 agent 能执行 shell 命令,就已经能用 renmy test 和 renmy explain 跑通整个循环。
AI agent 应该自己把 Apex 部署到 Salesforce 吗?
不应该。本地测试通过是必要条件,但不是充分条件,因为 org 里还有你的代码仓库中没有的元数据和自动化逻辑。部署请走 renmy deploy,它会先跑本地检查,然后在部署前针对相同的字节在 org 中做一次真正的仅校验验证;也可以走 renmy release validate 和 renmy release deploy,在验证和部署之间加入人工审批和不可篡改的回执。
renmy runtime 和 Nimbus 是同一个东西吗?
是的。Nimbus 在 2026 年 10 月更名为 renmy runtime。它是同一个二进制文件,来自同一条代码仓库线;nimbus 命令、NIMBUS_* 变量、nimbus.properties 以及 MCP 服务器的注册名 nimbus 都继续可用。更名记录见 renmy.net/blog/nimbus-is-now-renmy。
Nimbus 在 2026 年 10 月改名为 renmy runtime:工具还是同一个,二进制文件也没变。改名的记录在这里。
简单来说:AI 编程助手很擅长写 Python 和 TypeScript,原因是它们跑完自己写的代码,一秒内就能看到结果,一个任务里能这样来回几十次。可一碰到 Salesforce Apex 就卡住了,因为 Apex 只能在 Salesforce 组织(org)里运行,隔着网络,跑一次要等好几分钟。
renmy runtime 是一个本地运行的 Salesforce Apex 运行时:它可以直接执行真实的 Apex、SOQL、DML 和 Salesforce Flow。