aps-agent/Pi-Agent兜底能力详细方案.md

173 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Pi Agent 兜底能力 · 详细实施方案
> 版本 v2.0 · 2026-09-02 · 取代:`Pi-Agent接入计划.md` / `Pi-Agent接入详细计划.md`(那两份是"接入通道"定位,本方案是"**全系统兜底能力**"定位,范围显著扩大)
> 依据:`plan.md` §2.1/§2.2/§3、`PROJECT_OPERATING_RULES.md`、`docs/architecture/harness.md`、`docs/architecture/skills.md`、`docs/architecture/overview.md`
> 现状代码锚点:`server/aps_domain/workflow.py:2875`(当前 unknown 意图兜底 = 纯话术回复,**无能力**)、`server/agent_core/harness.py`(`_POWER_MAP` 62 项登记 + 未登记默认 P3 拒绝)、`server/agent_core/tool_runtime.py`(唯一执行入口)、`server/agent_core/mcp_bus.py`、`server/agent_core/feature_flags.py`(FF-01 开关机制)、`apps/desktop/sidecar.cjs`(子进程环境清洗/看门狗,Pi runtime 可直接复用这套模式)
---
## 1. 定位重述:什么是"兜底能力"
**现状**:用户说一句系统听不懂的话,走到 `workflow.py:2875` 的 `assistant.reply/unknown` 分支——LLM 回一段话术,**事情没办成**。已登记意图执行失败(求解器 fatal、数据缺字段、接口超时)也只有报错,没有自救。
**目标态**:Pi Agent 成为 APS 的**通用能力后备层**——产品化路径"不能办"或"办砸了"时,由 Pi 这个具备读/写/执行能力的通用智能体,在 Harness 划定的围墙内把事办成,并且全程可审计、可回滚、可熔断。
```
用户请求 → 意图管线
├─ 命中已登记意图 → 产品化路径(现状,快/稳/确定性)
│ └─ 执行失败 ──┐
└─ 未识别/未登记 ───┤
▼
【受治理的兜底车道 Governed Fallback Lane】
Pi 分析任务 → 产出《执行计划草稿》(P1,只读可直通)
→ 确认卡呈人类审批 (P2 起)
→ 批准后 Pi 在沙箱内执行(工具桥只暴露登记过的能力)
→ 执行后世界状态 diff 验证 + 报告
→ 全程审计链 + 证据链 + 可回滚 checkpoint
```
**一句话:Pi 是被 Harness 雇佣的临时工——有手艺,但进厂要登记、干活要批条、动设备要有人在场、出活要验收。**
## 2. 与产品宪法的冲突分析与消解
这是本方案最关键的一节。兜底能力天然想"什么都能干",宪法要求"未经授权什么都不能干"。逐条消解:
| 宪法红线(PROJECT_OPERATING_RULES 原文) | 表面冲突 | 消解设计 |
|---|---|---|
| 「动作必须经 `_POWER_MAP` 白名单登记,未登记默认 P3 拒绝」 | 兜底场景恰恰是"未登记意图" | 新增 3 个**元意图**登记进 `_POWER_MAP`:`agent.fallback.propose`=P1(产出计划草稿,沙盒语义)、`agent.fallback.execute`=P2(执行已批准计划)、`agent.fallback.execute.highrisk`=P3(涉主干写/外部系统,逐字段人工确认或默认拒绝)。Pi 从未"直接做事",它做的事都被这三个登记动作包裹 |
| 「LLM 只有提议权」(tool_runtime) | Pi 是 LLM 驱动的执行体 | Pi 的**计划**是提议;**执行**走 `/api/actions/confirm` 唯一通道。Pi 能调用的工具本身就是经过登记的意图封装(见 §4.3 工具桥),物理上无法直写 store/DB |
| 「不得引入未设计的隐式副作用」 | Pi 自由执行副作用不可枚举 | 沙箱围墙(§4.2):文件系统圈禁在 run 专属目录、网络只通 APS loopback、shell 白名单、环境变量清洗(复用 sidecar.cjs 的 allowlist 模式)。墙内副作用显式枚举,墙外物理不可达 |
| 「写前必须建 checkpoints 成对快照」 | Pi 执行前后状态未知 | 兜底车道**强制**执行前 checkpoint、执行后 world diff 验证报告,diff 摘要进确认卡和审计 |
| 「失败必须显式报告」 | LLM 倾向"圆场" | Pi 输出契约强制 `status: success|partial|failed|blocked`;`partial/failed/blocked` 必须附未竟事项清单;gateway 侧校验缺失字段即判 failed |
| 「mock/stub 不得进入产品路径」 | Pi 可能"假装"调用了工具 | 工具桥每次调用返回真实调用凭证(callId),Pi 报告中引用 callId 可被审计对账;无 callId 支撑的成果声明判无效 |
## 3. 场景矩阵(10 类兜底场景 × 治理策略)
| # | 场景 | 触发条件 | 权力 | 治理策略 | 验证方式 | Pi 干不了时的降级 |
|---|------|---------|------|---------|---------|------------------|
| S1 | **意图未识别**(新说法/新需求口令) | 意图管线产出 `unknown` | propose=P1 / execute=P2 | 计划草稿确认卡必出 | 执行后 diff + 用户确认回执 | 退回话术 + "已记录需求"工单 |
| S2 | **已登记意图执行失败**(求解器 fatal、数据缺字段) | handler 抛错/返回失败 | P1 诊断只读 / 修复=P2 | 诊断报告直通;修复动作出卡 | 重跑原意图成功即为验证 | 显式报错原文 + 诊断附件 |
| S3 | **新数据格式接入**(客户给了没人写过 importer 的 Excel/CSV/JSON) | data.import 解析失败或用户直接给文件 | P2(导入写主干) | 计划含字段映射表,确认卡呈现映射供审 | 导入后行数/金额对账 + 抽样比对 | 输出《手工整理指引》 |
| S4 | **缺算法/策略**(某工艺无现成排产策略) | flex.schedule 无匹配 skill 或用户明示"试个新策略" | P1(沙盒试排) | 仅沙盒语义,产物为草稿版本 | 沙盒 KPI 对比基线版本 | 明确告知"超出兜底能力" |
| S5 | **ad-hoc 分析/报告**("帮我看看哪条线最容易拖期") | report.generate/data.analyze 覆盖不了的自由分析 | P1 | 只读工具桥 + 沙盒计算 | 报告数字必须引用冻结快照字段(宪法既有规则) | 返回原始数据 + 分析失败说明 |
| S6 | **外部集成故障**(MES/WMS 接口挂了,要手工补录/对数) | integrations 调用失败告警 | P2 | 补录动作逐笔出卡 | 与外部系统恢复后对账 | 生成待补录清单(Excel)交人工 |
| S7 | **现场运维诊断**(support 工程师查日志/修配置) | 运维人员在运维入口显式发起 | P2;改配置 P3 | 仅运维角色可见入口;全程录屏级审计 | 修复后健康检查绿 | 输出诊断报告 + 建议人工操作 |
| S8 | **演示/售前救场** | 演示中任何上述场景 | 同对应场景 | 无特殊豁免(宪法) | 同对应场景 | 话术降级 |
| S9 | **批量数据处理**(一次性清洗/转换 5000 行工单) | 用户发起且无对应产品功能 | P2 | 计划含抽样预览(前 20 行变换结果)出卡 | 全量校验规则 + 抽样人工确认 | 分批+断点,失败批次显式列出 |
| S10 | **Pi 自身失败**(模型不可用/超时/超预算/死循环/部分写入) | 熔断器触发 | — | 超时(默认 10min)/步数(50)/token 预算三重熔断;部分写入由 checkpoint 回滚 | 回滚后 diff 为空即验证 | 显式失败报告 + 已回滚声明 |
**矩阵结论**:10 类场景中 S1/S2/S3/S5/S9 是价值主干(覆盖 80% 真实需求),S4/S6/S7 价值高但风险也高(放后期),S10 是必须设计的元场景。
## 4. 详细设计
### 4.1 组件清单(新增 4 个可重生模块 + 1 个外部进程)
| 组件 | 位置 | moduleId | 职责 |
|------|------|----------|------|
| FallbackLane 编排器 | `server/agent_core/fallback_lane.py`(新增,~600 行) | `core-fallback-lane` | 触发判定 → 任务简报 → 调 Pi → 收计划 → 出卡 → 执行 → 验证 → 审计 |
| Pi 工具桥 | `server/integrations/pi_bridge.py`(新增,~400 行) | `integ-pi-bridge` | 向 Pi 暴露围墙内工具集(§4.3),每次调用发 callId 凭证 |
| 兜底验证器 | `server/agent_core/fallback_verify.py`(新增,~300 行) | `core-fallback-verify` | 执行后 world diff、规则校验、报告生成(数字只许来自冻结快照) |
| 熔断与预算 | 并入 fallback_lane(~150 行) | 同上 | 超时/步数/token 三重熔断 + audit_alerts 联动 |
| Pi runtime 进程 | Node 进程(`pi-agent-core` headless 模式) | — | 被编排器以子进程拉起,生命周期管理**复用 sidecar.cjs 的 SidecarManager 模式**(端口/nonce/环境清洗/看门狗/日志轮转全套照搬) |
### 4.2 沙箱围墙(自内向外四层)
```
L1 工具层:Pi 只能看见工具桥暴露的工具(§4.3),没有裸 fs/shell/net
L2 文件层:cwd 圈禁 ~/.aps/fallback/<runId>/(Web 态 server/data/fallback/<runId>/);
可读注入区(用户上传文件副本)、可写工作区、产物出口目录三区分离
L3 网络层:仅允许 127.0.0.1:<gateway port>;模型 API 出口走 gateway 代理(可关)
L4 进程层:环境变量清洗(CONDA/Python 变量剥离,照搬 buildChildEnv)、
父进程看门狗、taskkill 进程树回收、10MiB 日志轮转
```
> 说明:Pi 官方支持 Gondolin/Docker 沙箱,但工业现场 Windows 离线机器上 Docker 不可靠,故以 L1-L4 进程级围墙为主,Docker 沙箱作为 Web/服务器部署的可选加强项。
### 4.3 工具桥暴露面(围墙内 Pi 的全部"手艺")
| 工具 | 包装自 | 权力 | 说明 |
|------|--------|------|------|
| `aps_invoke(intent, params)` | `/api/agent/invoke`(即 handle_intent) | 随意图 | **Pi 写世界的唯一方式**,内部仍过 _POWER_MAP/确认卡 |
| `aps_query(sql_like)` | master.query / data.analyze 只读集 | P0 | 世界状态只读视图 |
| `knowledge_query(q)` | `/api/rag/query`(ragScopes 鉴权) | P0 | 知识库 |
| `fs_read/fs_write(path)` | 沙箱 L2 三区 | — | 物理圈禁,越界即 EACCES |
| `shell_run(cmd)` | 白名单(python 脚本、xlsx 处理等显式登记命令) | — | 每条命令正则白名单 + 参数审查 |
| `checkpoint_create()` | state checkpoints | — | Pi 可主动建回滚锚点 |
| `report_emit(md)` | fallback_verify | — | 产物唯一出口,强制走验证器 |
### 4.4 意图与权力登记(harness 变更)
```python
# _POWER_MAP 新增 3 项(harness.md 权力矩阵同轮更新)
"agent.fallback.propose": "P1", # 产出执行计划草稿(沙盒语义,不写主干)
"agent.fallback.execute": "P2", # 执行已批准计划 → 确认卡
"agent.fallback.execute.highrisk": "P3", # 涉外部系统/主干批量写 → 默认拒绝,白名单放行
```
确认卡内容(P2 出卡时必须冻结):计划步骤清单、每步工具与权力、预计影响面(目标实体清单)、`evidenceRefs`、执行前 checkpoint id、回滚方式。**卡片上的承诺即执行上限**——执行时逐步比对,Pi 偏离计划即熔断(计划外工具调用 → blocked)。
### 4.5 证据链与审计
- 每次兜底运行:`runId` 贯穿 propose→confirm→execute→verify 全链;
- Pi 每步工具调用:TOOL 审计(actor=`pi-fallback:<runId>`、callId、入参摘要、结果摘要);
- 确认卡批准/拒绝:GATE 审计(既有机制);
- 验证报告:REPORT 审计 + 产物落 `~/.aps/fallback/<runId>/report.md`;
- 全链可通过既有 `/api/gov/audit` 按 runId 过滤回放。
### 4.6 开关与熔断(复用 FF-01)
- `features.json` 新增 `"fallback": false`——**默认全关**,现场按需开;开关本身 P2 确认卡管理;
- 熔断三闸:单次运行超时 10min / 步数 50 / token 预算(可配);日维度累计预算;
- 触发熔断 → 显式失败 + checkpoint 回滚 + audit_alerts 通知。
## 5. 部署形态(两个大坑,提前说)
| 形态 | 方案 | 坑 |
|------|------|-----|
| **Web/服务器部署** | docker-compose 增加 `pi-runtime` 服务(Node 22 + pi-agent-core) | 小,标准做法 |
| **桌面端打包** | PyInstaller sidecar 之外再加 Node runtime(~60-80MB)打进安装包,或做成**可选组件**首次使用时下载 | ① 体积恶化(与 Tauri 瘦身诉求矛盾,两事更该串行决策);② **离线工厂没有模型 API 出口**——兜底重度依赖 LLM,断网即瘫。对策:模型出口走 gateway 代理可配内网模型网关;无模型时 fallback 开关强制关闭且 UI 明示原因(失败显式,不装死) |
## 6. 阶段计划(修订版,替代 v1.0 计划)
| 阶段 | 内容 | 工期 | 出口标准 |
|------|------|------|---------|
| **P0 PoC** | 单场景 e2e 打穿:S5(ad-hoc 分析)。Python 编排器拉起 Pi headless → 计划 → 假确认 → 沙箱执行 → 报告。**不碰产品路径**,全部在 `poc/` | 4-5 人日 | 一个真实分析任务从发起到报告全链跑通;四层围墙验证有效(故意越狱测试被拒) |
| **P1 只读兜底** | S1(只读类)/S5/S9-只读部分 进产品路径;fallback_lane + pi_bridge 转正;`agent.fallback.propose` 登记;FF-01 开关接入 | 7 人日 | 意图未识别时用户能拿到"办成的事"而非话术;越狱/注入黄金测试 10 例全拦 |
| **P2 沙盒写兜底** | S2/S3/S9 写路径;`agent.fallback.execute`=P2 出卡;checkpoint 强制 + diff 验证器;熔断三闸 | 10-12 人日 | 新格式 Excel 导入从"给文件"到"对账通过"全链路演示绿;计划偏离熔断测试通过 |
| **P3 高风险与运维** | S4/S6/S7;`execute.highrisk`=P3;运维入口与角色门禁;集成故障对账流 | 7-10 人日 | MES 断连补录场景验收;运维全程审计可回放 |
| **P4 评估与硬化** | 兜底质量 golden 集(30+ 场景用例:成功率/误写率/确认轮次/token 成本四指标);prompt 注入防护集(工单备注藏指令等 20 例);离线降级演练 | 8 人日 | golden 集成功率 ≥85% 且误写率 0;注入集 100% 拦截 |
| **P5 验收发布** | 全量黄金(1071+ 基线)、桌面打包冒烟(含可选组件)、文档同轮、现场 runbook | 5 人日 | 发布门禁全绿;康尼数据集真实验收 |
| **合计** | | **41-47 人日(1 人约 8-10 周)** | |
### 里程碑视图
```
W1 W2-3 W4-6 W7-8 W9-10 W11
[P0] → [P1 只读] → [P2 写兜底] → [P3 高风险] → [P4 硬化] → [P5 发布]
↑go/no-go ↑已可演示价值 ↑核心能力闭环 ↑按需可裁剪 ↑质量门禁
```
## 7. 风险登记册(兜底定位特有)
| # | 风险 | 等级 | 对策 |
|---|------|------|------|
| F1 | **非确定性**:同一请求两次兜底结果不同 | 🔴 | 计划审批制(人看的是计划不是黑盒)+ golden 集回归 + 产物必须经验证器,不靠 Pi 自述 |
| F2 | **Prompt 注入**:订单备注/导入文件里藏"忽略之前指令" | 🔴 | 注入防护 golden 集(P4);用户数据进 Pi 前包裹隔离标记;工具桥不认 Pi 的"用户已确认"自述——确认只信 gateway 会话内的真实确认卡 |
| F3 | **部分写入**:执行到一半熔断 | 🟡 | checkpoint 强制前置 + 回滚验证(diff 为空才算回滚成功) |
| F4 | **成本失控**:LLM token 烧穿预算 | 🟡 | 三闸熔断 + 日预算 + audit_alerts |
| F5 | **离线工厂无模型出口**,兜底变废铁还误导用户 | 🟡 | 无模型时开关强制关 + UI 明示原因;支持内网模型网关地址配置 |
| F6 | **Node runtime 进桌面包** | 🟡 | 可选组件化;与 Tauri 决策串行 |
| F7 | **"兜底兜不住还装兜住"**(LLM 圆场) | 🔴 | 输出契约强制 status 字段 + callId 对账(§2 最后一行),圆场在网关层被物理判失败 |
| F8 | 团队对"治理下通用智能体"的调试经验不足,问题定位难 | 🟡 | 全程 runId 可回放 + Pi trace 落盘;P0 即建立调试工具链 |
| F9 | 范围蔓延:兜底太好用 → 产品化路径荒废 | 🟢 | 治理指标:兜底触发率应随产品化下降;触发率周报,高的场景反哺产品化立项 |
## 8. 与 v1.0 接入计划的关系
v1.0 的 `/api/agent/` 适配层、Agent Token、MCP 总线登记**全部保留**——它们在本方案中变成工具桥的基础设施(`aps_invoke` 就是走那层面)。外向接入(人在 Pi 终端里用 APS)成为 P1 完成后的副产品,不再单独排期。
## 9. 三条决策建议
1. **先 P0 后承诺**:4-5 人日的 PoC 直接验证最危险的两个未知数(围墙有效性、计划审批可用性),PoC 不过则退回 v1.0 纯接入定位;
2. **S 场景分批上线**:P2 之后每批场景单独灰度(FF-01 开关粒度到场景),不一锅端;
3. **与 Tauri 串行已定**,再强调一次:F6 意味着如果未来迁 Tauri,Node runtime 的打包方案要一起重设计。