2.9 KiB
2.9 KiB
ADR-0006:引擎以长驻子进程运行
- 状态:已接受
- 日期:2026-09-23
- 决策人:技术负责人
- 相关:任务表 A3(决策 D10);设计文档《架构设计》5.1、5.2
背景
平台需要一个智能体循环来理解意图、挑工具、解释结果。这一循环跑在哪,决定了三件事:故障隔离、进程模型的复杂度、以及工具怎么交给引擎。
两项事实约束着选择:Codex 是 Rust 二进制,只能以子进程驱动,无法进程内嵌入;Pi 提供两种形态——进程内库(SDK),以及长驻子进程(RPC 模式,官方附带 RpcClient 客户端库)。若一个进程内、一个子进程,适配层要维护两套进程模型。
另有一个运行期问题:Node 是单线程。智能体循环与平台服务同进程时,长任务会挤占事件循环,影响所有会话的响应。
选项
| 选项 | 做法 | 代价 | 不选的理由 |
|---|---|---|---|
| A 引擎都进程内 | Pi 进程内、Codex 也进程内 | 无 IPC 开销 | Codex 无法进程内嵌入,此路不通 |
| B 引擎都子进程 | 两个引擎都以长驻子进程运行,平台通过各自官方客户端通信 | Pi 侧要写扩展桥与进程管理 | 选定 |
| C Pi 进程内 + Codex 子进程 | 维持现状 | 无需新增工作 | 两套进程模型;智能体循环与平台争抢事件循环 |
结论
选 B:两个引擎都以长驻子进程运行,由平台拉起与守护。
- Pi:子进程 +
RpcClient,协议是标准输入输出的 JSONL - Codex:子进程 + app-server 协议
- 平台侧只认统一的
AgentRuntime接口,不感知两者协议差异
首版一个会话对应一个引擎进程;若进程数成为负担,再评估进程复用(Pi 支持会话切换,Codex 支持多线程复用)。
影响
- 隔离:智能体循环不再占用平台的事件循环,长任务不拖累其他会话
- 工具面仍然不同,没有统一:Codex 可通过 MCP 或实验性动态工具接收平台能力;Pi 需要在 pi 侧写一个扩展,注册工具并把调用以本地 HTTP 回调平台,平台再走
Core.invoke。该链路的鉴权复用现有模式:loopback 随机端口 + nonce 注入 + origin 校验 - 进程管理是共用的:启停、超时、崩溃重启、日志轮转、父进程看门狗只写一套;可借鉴现有 Electron sidecar 的实现
- 对代码:
server/agent增加引擎进程管理与 Pi 扩展桥;Pi 扩展放在 pi 侧的扩展目录,由平台启动子进程时指定 - 对任务:A3.3 改为以子进程接入;新增两个工作包(引擎进程管理、Pi 扩展桥)
- 不可省:无论哪个引擎,工具调用只有一个出口
Core.invoke
遗留
- Pi 扩展桥的鉴权细节:nonce 轮换周期、端口预留策略,在 A3 设计时定
- 引擎进程的复用策略(一进程一会话还是一款多会话)首版不做,观察实际进程数后再评估