跳到正文

外部智能体(ACP)

Chimera 可以把一次编码回合交给它没有编写的智能体 —— Claude Code、Gemini CLI,或任何讲 Agent Client Protocol 的适配器。对话记录、验证器、快照和撤销仍然属于 Chimera;干活的是别人。

为什么

Chimera 的主张从来不是它的循环是唯一好的循环,而是围绕循环的治理:污染台账、写入区域、回合前的快照、 回合后的裁决、说明真实发生了什么的回执。这些对任何执行者都成立。拒绝驱动一个你本就信任的执行者,等于 死守产品中最没意思的那一半。

什么有保证,什么没有

请在安装之前读这一节,因为它决定这个功能是否适合你。

ACP 智能体会声明它将使用客户端的哪些能力,而 Chimera 提供 fs/read_text_filefs/write_text_file提供不等于强制。 值得驱动的智能体都有自己的文件与终端工具:Claude Code 通过 Claude Agent SDK 写入,并没有义务先问我们。

具体地说:

Chimera 自身的循环 外部智能体
写入区域拒绝区域外的写入 总是 仅限经过我们的调用
Shell 在配置的沙箱中运行 总是 智能体按自己的方式执行
污染台账触发危险工具闸门 总是 仅限我们中转的工具
回合前对工作区做快照
一键撤销整个回合
每次授予的权限都进回执

最后三行才是真正的保证,也正是选中外部智能体时「代码」界面那行状态所承诺的内容。它不再说「在 /project 内编辑,不执行命令」——那句话描述的是 Chimera 拥有的工具——而是说已经先做了一份副本,整个 回合可以撤销。保留更强说法的界面,就是在做一个这个回合无法兑现的承诺。

Chimera 还拒绝了 ACP 的终端能力。由我们托管的终端会成为沙箱之外的第二条执行路径,却没有沙箱的任何 规则。

安装

对 Chimera 已知的智能体无需配置:

npm i -g @agentclientprotocol/claude-agent-acp   # Claude Code,需要 Node 22+
npm i -g @google/gemini-cli                       # Gemini CLI(其 ACP 模式在上游标记为实验性)

然后看看这台机器实际能跑什么:

chimera doctor

external_agents 会逐个报告 available: true/false,为 false 时还会给出解决它的那行命令。可用性是在 运行 sidecar 的那台机器上判定的 —— 对于打包好的桌面版,那是一台由 CI 组装、没人看过的机器。也就是说: 「它应该在那儿」不是证据。

桌面应用会在输入框上方显示一行由谁执行,列出 doctor 找到的项。当没有任何可运行的项时,这一行根本 不出现;「你还没有这个,装法如下」属于 doctor

凭据

Chimera 启动的每个子进程拿到的环境都会剥掉 API_KEY / TOKEN / SECRET 变量,这样 shell 命令就无法 回显供应商密钥。而 ACP 智能体是一个整份工作都依赖密钥的程序,所以每个智能体按名字声明它需要的变量, 也只有这些会被放回去:

  • Claude Code:ANTHROPIC_API_KEYANTHROPIC_AUTH_TOKENANTHROPIC_BASE_URLCLAUDE_CONFIG_DIR
  • Gemini CLI:GEMINI_API_KEYGOOGLE_API_KEYGOOGLE_APPLICATION_CREDENTIALS

直接透传整个环境更省事,也等于把机器上的每一把钥匙交给将来的每一个适配器。

自定义适配器

Codex 等通过本项目没有跑过的第三方适配器接入 ACP。与其列出一条未经验证的命令 —— 那会把「我们没检查」 变成「已支持」—— 不如把 Chimera 指向你手上的那个:

// POST /api/code/turn
{
  "message": "修好那个失败的测试",
  "provider": "custom",
  "provider_command": "npx -y some-acp-adapter --flag"
}

命令按 shell 风格切分,但不经过 shell 执行,所以一个多余的管道符只是一个参数,而不是第二条命令。在 Windows 上,含有 cmd.exe 语法(& | < > ^ %)且会送到 .cmd 启动器的参数会被拒绝而不是转义:不同启动器 的引号规则并不相同,猜错就会执行你的机器,而不是机器上的某个程序。

工作原理

  • 每个会话一个子进程,而不是每个回合一个。session/prompt 是智能体所保有的上下文中的一条消息; 每次都新起进程会让每个回合都变成第一回合。
  • 同时最多四个存活,闲置一小时的会被关闭。每一个都是持有模型连接的进程。
  • 进程在自己的进程组中启动,并按树杀死 —— 编码智能体是启动器,只杀掉我们持有的那个进程,会留下仍在跑的 工作进程和被占住的文件夹。atexit 收尸器覆盖了回合进行中退出应用的情况。
  • 智能体的 session/update 通知被翻译成原生循环发出的同一批事件,所以界面不需要第二套实现。思考片段 被丢弃而不是混入答案;diff 块会变成对话记录本就渲染的统一 patch。
  • 原生循环拥有而这里无法报告的数字 —— stepscontext_peak_tokens —— 以 null 而非 0 返回。零会 被读成「它什么都没做」。

局限

  • 权限请求一律以 allow_once 回应,并记入回执。拦下一个智能体本来就不必提出的请求是演戏;诚实的 做法是授予、记录,并依靠快照 —— 它同样覆盖那些从未询问过的写入。
  • 融合、角色、记忆和仓库地图属于 Chimera 自身的循环。外部回合会报告 fused: false 且没有记忆使用, 因为这些都没有发生。
  • Gemini 的 ACP 模式在上游标记为实验性,其行为可能在版本之间变化。

在 GitHub 上编辑本页