news 2026/10/15 18:11:52

WhipCode RLM运行时揭秘:模型如何用Starlark和JavaScript驱动工具?rlm_exec完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WhipCode RLM运行时揭秘:模型如何用Starlark和JavaScript驱动工具?rlm_exec完整指南

【免费下载链接】whip

A fast coding-agent harness in Go. Tool-use loop, bubbletea TUI, provider-routable models with live catalog discovery, MCP support, background subagents. One binary, no runtime, built for open-source models.

项目地址:https://gitcode.com/gh_mirrors/whip3/whip
点击查看免费下载

WhipCode 是一款用 Go 编写的快速编程智能体(coding agent),它的核心是 RLM 运行时——模型通过唯一工具rlm_exec执行 Starlark 或 JavaScript(QuickJS)单元(cell),从而调用文件、Shell、消息、MCP 等宿主模块,实现递归委派与工具调用。本文将带你完整理解这套执行模型的工作原理、两种语言的选择方式,以及默认限额等关键细节。

一、什么是 WhipCode RLM 运行时:编程智能体的执行模型

大多数编程智能体靠"不断增长的对话记录 + 一堆零散工具"来工作,上下文越长越慢、越贵。WhipCode 的 RLM(Recursive Language Model,递归语言模型)运行时换了一种思路,它有四个设计目标:

  1. 大上下文始终可用,但不必反复塞进提示词;
  2. 递归委派使用统一的会话抽象(根节点和子节点是同一种AgentSession);
  3. 协调、权限、预算与恢复全部持久化;
  4. 所有副作用都收拢在 daemon 拥有的单一策略边界之后。

在这套模型里,会话没有"模式"字段,也没有"直接工具"模式——每个模型能看到的工具只有rlm_exec一个。它由 daemon 托管、独立于 UI 运行,关闭窗口不会中断会话。

💡 如果你在终端里使用它,启动时会看到这样的 TUI 界面(bubbletea 构建):

二、rlm_exec 深度解析:模型看到的唯一工具

rlm_exec的定义在 internal/rlm/tool.go。它接收一个参数:code(源代码字符串),然后在受限内核(kernel)中执行一个"有界单元"。可以把它理解为一个带超时的 REPL:

# 一次 rlm_exec 调用(Starlark 单元) content = files.read(path="README.md")["output"] print("项目名:", content.split("\n")[0])

模型每写一小段代码,运行时就执行一小段。执行结果是一个 JSON 对象,包含value(返回值)、output(打印输出)、steps(执行步数)以及检查点通知等字段;超过 16 KiB 的值会被截断为value_preview并标记truncated: true,保证返回给模型的上下文永远有界。

几个关键约束(新手最常踩的坑):

  • 宿主模块操作只接受关键字参数,如files.read(path="README.md");
  • Starlark 不是 Python:没有try/except、import、open;
  • QuickJS 不是 Node.js:没有require、npm、定时器、文件系统 API;
  • files/shell的结果是 JSON 对象而非字符串:小结果文本在output字段下,超过 8 KiB 则返回handle、size和 4 KiB 预览,需用context.read(handle=..., offset=0, length=8192)分片读取。

三、Starlark vs JavaScript:两种执行语言怎么选?

新会话可以在创建时选择执行语言,默认是 Starlark;CLI 上用--rlm-engine指定,例如:

whipcode --rlm-engine quickjs

运行中的会话不能中途切换语言;子会话继承根会话的选择,恢复会话时用错误的语言参数会直接报错。引擎描述符定义在 internal/rlm/engines.go,QuickJS 引擎运行在一个内嵌的 WASM 构建(wazero 执行)中,源码见 internal/rlm/engine/quickjs/。

两种语言的核心差异:

维度Starlark(默认)JavaScript(QuickJS)
调用宿主模块关键字参数:files.read(path=...)await files.read({path: "..."}),支持顶层await
并发宿主调用串行(1 个)最多 16 个并发
检查点保真度部分保真:保存受支持的顶层数据与助手函数整堆保真:闭包、循环引用、类实例、BigInt 全量保存
状态恢复恢复受支持的数据子集与无状态依赖的顶层def完整恢复整个 JS 堆(词法绑定、闭包、对象同一性)
典型适用简单、稳态逻辑复杂状态、异步并发扇出、Promise.all批量调用

JavaScript 单元的典型写法:

const [a, b] = await Promise.all([ files.read({path: "go.mod"}), files.read({path: "package.json"}), ]); console.log(a["output"].split("\n")[0]);

⚠️ 注意:QuickJS 的宿主负载是"被动 JSON 树",超大整数用BigInt,例如BigInt("9007199254740993");不安全的整数 Number 和访问器(accessor)会在宿主边界被拒绝。

四、宿主模块全览:单元里能调用哪些能力

所有宿主模块注册在 internal/rlm/modules.go,内核只能看到其定义所选模块的子集——选择是强制执行的:宿主会拒绝调用清单之外的任何模块。常用模块一览:

模块能力常用操作
files文件读写list/search/read/write/patch
shell命令执行run(阻塞,120s 上限)、start/poll/tail/wait/kill(后台任务)
context自身历史检索inspect/search/read/history
agents递归委派spawn/submit/wait/inspect/stop
messages节点间邮箱send/list/read/complete/defer
mcpMCP 服务器工具search/describe/list_tools/call
models无状态模型调用call/batch
state持久化状态private_set/blackboard_get/subscribe
browser桌面浏览器控制open/attach/run/detach
artifacts/schedules/permissions/user大对象、定时任务、权限请求、询问用户略

递归委派是 RLM 的招牌能力:agents.spawn(prompt=..., name=...)会立即返回子代理元数据,父代理结束本轮,等子代理完成或来信后由邮箱"唤醒"新回合。长任务(构建、测试、服务器)应通过shell.start` 放到后台,每个代理最多 8 个并发任务。

五、检查点与状态持久化:重启后工作不丢

每个单元执行结束后,内核都会保存一个检查点。这意味着 worker 进程被回收、甚至 daemon 重启后,状态都能恢复:

  • Starlark:顶层全局变量持久化在存活 worker 中;支持的数据子集(None、布尔、整数、浮点、字符串、字节、列表、元组、字典)直接重建。闭包、循环引用、容器里的函数会被跳过并在scratch通知中报告;
  • QuickJS:快照捕获整个 JS 堆——词法绑定、闭包、类、BigInt 都跨重启存活。忘记await的调用会被排干,未处理的 rejection 会显式失败;
  • 检查点带 SHA-256 完整性校验,绑定引擎 build/ABI/profile,损坏或不兼容的镜像会显式失败,而不是被静默覆盖。

📌 官方建议:重要的持久信息应写入state、artifacts、messages或子代理记录,而不是只留在单元变量里。

上下文管理同样是 RLM 的一部分:原始转录保持只增不改,模型视图聚焦到最近少量对话加一个有界摘要;历史、工具参数和分片内容在压缩、重启后依然可通过context.search/context.read检索。

六、rlm_exec 执行限额:默认值一览

每个单元都是"有界"的,默认限额定义在 internal/rlm/kernel.go(可用rlm.*配置项调整):

配置项默认值含义
rlm.steps1,000,000Starlark 单元步数上限
rlm.hostRequests1,024每单元宿主调用次数
rlm.wallMillis30,000单元计算时间上限(宿主调用耗时不计入)
rlm.memoryMiB256worker 内存上限
rlm.outputBytes65,536单元捕获输出上限
rlm.maxWorkers16全 daemon 存活内核数

QuickJS 另有:32 MiB 访客堆、16 个并发宿主调用、10 分钟整单元看门狗。这些是执行边界;token、成本、时长等"持久预算"由会话层单独核算。

七、可观测性:实时追踪 rlm_exec 执行过程

单元在运行时是"可观看"的:打印输出会节流推送到stream.tool.output,每个宿主调用都会发出stream.cell.host事件(模块.操作、参数摘要、耗时、错误)。客户端因此可以为任意节点渲染一个实时 REPL,而不占用模型的上下文——桌面端右侧的"执行追踪"面板就是这一机制的体现(见本文首图)。

八、延伸阅读与关键路径

  • RLM 运行时完整设计:docs/rlm-runtime.md
  • rlm_exec工具定义:internal/rlm/tool.go
  • 宿主模块注册表:internal/rlm/modules.go
  • 引擎描述符(Starlark/QuickJS):internal/rlm/engines.go
  • QuickJS 内核泵:internal/rlm/quickjs_kernel.go
  • 模型侧运行指南(Starlark 版):internal/rlm/testdata/TestDefinitionPromptGolden/coding/starlark/guide.golden
  • 语言选择与恢复冲突:docs/setup.md
  • 确定性 RLM 评估:evals/rlm/

常见问题速答

  • 为什么模型只有一个工具?统一接口让根节点和子节点行为一致,副作用全部走 daemon 策略边界,权限与预算才真正可控。
  • Starlark 单元失败会回滚吗?不会。单元完成的外部副作用保留;检查点失败不回滚已完成的效果,也不要为"修复检查点"重复执行有副作用的操作。
  • 能否让模型自己挑语言?不能在运行中切换;由创建时元数据或--rlm-engine决定,子节点继承。

WhipCode 的 RLM 运行时,本质是把"智能体循环"变成了"带检查点的代码执行":模型写短小的 Starlark 或 JavaScript 单元,宿主模块负责一切副作用,预算、权限和恢复交给 daemon。理解了rlm_exec这一个工具,就理解了 WhipCode 的全部工作方式。🚀

【免费下载链接】whip

A fast coding-agent harness in Go. Tool-use loop, bubbletea TUI, provider-routable models with live catalog discovery, MCP support, background subagents. One binary, no runtime, built for open-source models.

项目地址:https://gitcode.com/gh_mirrors/whip3/whip
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:10:07

询盘要不要自动分给不同的销售?看团队规模再定

外贸公司处理询盘,大致有两种状态:一种是询盘一来,群里立刻有人抢着回;另一种是询盘堆在公共邮箱里,三天后才有人想起来看。询盘要不要自动分给不同的销售,答案不是简单的"要"或"不要"…

作者头像 李华
网站建设 2026/10/15 18:09:31

VS2022自编译OpenCV 4.8.0完整包,集成人脸识别模块实战

简介:面向 Windows 10 与 VS2022 开发者的 OpenCV 4.8.0 完整编译包,整合 opencv_contrib-4.8.0 后重新编译,涵盖全部官方模块及人脸识别、机器学习等扩展功能,解决官方发行版不含 contrib 模块、无法直接使用 face 接口的问题。压…

作者头像 李华
网站建设 2026/10/15 18:09:13

ethers.js事件过滤机制全解:从Log到queryFilter实战

先说明一个事实:ethers.js 的事件过滤,本质上不是在“拦截”事件,而是在链上日志(Log)里做检索。合约里 emit 出去的事件会以日志形式永久写进区块,ethers 能做的,是通过一组过滤条件,从海量的…

作者头像 李华
网站建设 2026/10/15 18:08:51

openSMILE 3.0音频特征提取实战:从安装配置到Python对接

简介:openSMILE 3.0 的 Windows 64 位安装包,面向语音情感识别、音乐信息检索与音频特征工程方向的研究者、算法工程师及学生。它解决在 Windows 环境下快速部署开源音频特征提取工具链的问题,无需自行编译即可调用底层特征计算能力。压缩包共…

作者头像 李华
网站建设 2026/10/15 18:08:27

GPIO模拟I2C驱动开发实战:海思平台时序实现与避坑指南

简介:一套面向海思平台的通用输入输出口模拟I2C总线驱动源码包,主要为了解决在没有硬件I2C控制器或希望节省芯片资源时的通信需求。压缩包共3个文件,包括一个C语言源文件、一个头文件以及一个Makefile构建脚本,整体大小仅为4KB&am…

作者头像 李华