Skip to content

88. Open-Agents 对标补齐方案 (Open-Agents Parity v1.0)

状态: ✅ Phase 1–5 全部落地(3 agent tools + Skill $ARGUMENTS + Sub-agent Profiles + prepareCall turn-scoped context + provider-options 三层深合并, 158 new tests pass) 日期: 2026-04-15 作用范围: packages/clidesktop-app-vue/src/main/ai-engine对标对象: vercel-labs/open-agents — Vercel Labs 2025-12 开源云端 Coding Agent 参考蓝本 关联文档: 78. CLI Agent Runtime · 81. 轻量多 Agent 编排 · 83. 工具描述规范统一 · 85. Hermes Agent 对标


1. 概述

1.1 背景

Open-Agents 是 Vercel Labs 开源的 Coding Agent 参考实现,核心采用 Vercel AI SDK v5 + ToolLoopAgent 模型,三层解耦 Web → Agent → Sandbox。通过系统性对比,在「CLI Agent 工具集」「Skill 模板能力」「Subagent 编排」「LLM Provider 参数治理」「Turn-scoped 上下文」五个维度存在可补齐的空白。

本方案只补齐缺失项,不触碰 ChainlessChain 既有优势

  • ❌ 不动:Durable Workflow / Vercel Sandbox(我们有 sub-runtime-pool + file-sandbox,架构已分离)
  • ❌ 不动:11 工具中已有的 8 个(read/write/edit/grep/bash/task/skill + edit_file_hashed 更强)
  • ❌ 不动:AI SDK / AI Gateway(我们自有 llm-manager 多 provider 路由)
  • ✅ 补齐:3 个缺失 agent 工具 + Skill $ARGUMENTS + Subagent Registry + Turn-scoped prepareCall + Provider-options 深合并

1.2 对标差距总览

维度open-agentsChainlessChain 现状差距等级方案
agent 工具:web_fetchweb_fetch 工具注入 agent loop仅 CLI 命令 browse fetch,agent 不可调用HIGHPhase 1
agent 工具:todo_writetodo_write + 内置 TODO 状态管理无 agent tool(有 CLI 命令但非 loop 工具)HIGHPhase 1
agent 工具:ask_user_question结构化提问暂停 agent 等待回复slot-filler.js 提及未注册MEDIUMPhase 1
Skill $ARGUMENTS 占位符SKILL.md body 运行时文本替换SKILL.md 无占位符支持MEDIUMPhase 2
Skill directory 路径注入自动前置 Skill directory: <abs>LOWPhase 2
Subagent Registry 声明式SUBAGENT_REGISTRY + buildSubagentSummaryLinescowork debate/compare/analyze 硬编码 roleMEDIUMPhase 3
prepareCall turn-scoped 上下文每 turn 注入 sandbox/skills/模型覆盖agent-repl messages 一次性构建MEDIUMPhase 4
Provider-options 三层深合并defaults ← modelId 推断 ← call overridesllm-manager 仅决定 provider+modelMEDIUMPhase 5
Ultracite (oxlint+oxfmt)替代 ESLint/PrettierESLint + 现状LOW附录(评估)

1.3 已有优势(不重复造轮子,保留不动)

  • edit_file_hashed: 内容哈希锚定行编辑,open-agents 的 edit 仍是纯字符串匹配,我们更强
  • git 工具: open-agents 只有 bash,我们有独立 git 工具 + 策略元数据
  • search_sessions + FTS5: 跨会话搜索能力
  • 146 内置 Skills + 4 层加载: 远超 open-agents 的 skills/discovery 简易实现
  • sub-runtime-pool: 子进程池 + sessionId 分片,比 open-agents 单沙盒更灵活
  • 4 层记忆 + Hooks 三件套: Hermes 对标已补齐,open-agents 都不具备

1.4 系统架构

┌─────────────────────────────────────────────────────────────┐
│              Agent REPL (CLI 入口,不变)                     │
├─────────────────────────────────────────────────────────────┤
│  Agent Core  (新增 3 工具 + 每 turn prepareCall)             │
│  ┌─────────┐┌─────────┐┌────────────┐ [既有 13 工具]        │
│  │web_fetch││todo_write││ask_user_   │ read/write/edit/     │
│  │         ││         ││question    │ grep/bash/git/...     │
│  └─────────┘└─────────┘└────────────┘                       │
├─────────────────────────────────────────────────────────────┤
│  Subagent Registry (新增,声明式)                            │
│  explorer (只读) / executor (全权限) / design (前端)         │
│  + 既有 cowork debate/compare/analyze 迁移到 registry        │
├─────────────────────────────────────────────────────────────┤
│  Skill Parser (增强)                                        │
│  $ARGUMENTS 占位符 + Skill directory 注入                   │
├─────────────────────────────────────────────────────────────┤
│  LLM Manager (增强)                                         │
│  resolveCategory → mergeProviderOptions 三层深合并           │
│  provider defaults ← modelId 推断 ← per-call overrides      │
└─────────────────────────────────────────────────────────────┘

2. 实施方案

Phase 1: Agent 工具三件套补齐 ✅

影响: HIGH | 工作量: MEDIUM | 实际测试: 59 新增 tests 全绿(todo-manager 15 + web-fetch 22 + agent-core 执行路径 7 + 既有 5 项计数/列表更新)

落地位置:

  • packages/cli/src/runtime/coding-agent-policy.cjs — 新增 web_fetch / todo_write / ask_user_question 策略条目
  • packages/cli/src/runtime/coding-agent-contract-shared.cjs — 新增 3 tool contracts(tier=extension)
  • packages/cli/src/runtime/agent-core.js — executeToolInner 新增 3 case 分支
  • packages/cli/src/lib/todo-manager.js — session TODO 存储 + 校验(单 in_progress / 唯一 id)
  • packages/cli/src/lib/web-fetch.js — SSRF 防护 + HTML→MD + 重定向链安全检查
  • packages/cli/__tests__/unit/todo-manager.test.js / web-fetch.test.js — 37 独立单测
  • AGENT_TOOLS 从 13 → 16;Ollama 请求 tools 数同步调整

2.1.1 web_fetch 工具

差距: 现有 packages/cli/src/commands/browse.js 是 CLI 子命令,agent loop 无法调用。

方案:

  • coding-agent-contract-shared.cjs 新增 web_fetch 契约
  • inputSchema: { url: string, format?: "markdown"|"html"|"text", maxBytes?: number }
  • 实现复用 packages/cli/src/lib/browser-automation.js 的 fetch 逻辑,默认 markdown 抽取(readability-like)
  • 策略元数据:riskLevel: "medium", availableInPlanMode: false, requiresPlanApproval: true(避免任意 URL 滥用)
  • 白名单域名 / 大小限制从 unified-config-manager.chainlesschain/config.json:webFetch

2.1.2 todo_write 工具

差距: agent 没有结构化 TODO 管理能力,复杂任务靠模型自己维护自然语言计划。

方案:

  • 新增 packages/cli/src/lib/todo-manager.js:session 内 TODO 列表(内存 + 可选持久化到 session record)
  • 工具契约 todo_write: { todos: [{ id, content, status: "pending"|"in_progress"|"completed"|"cancelled" }] }
  • 状态规则:单一 in_progress(强制),完成即时标记
  • 与 Plan Mode 集成:Plan 审批通过时自动写入初始 TODO 列表
  • REPL /todo 命令查看当前 session 的 TODO

2.1.3 ask_user_question 工具

差距: agent 遇到歧义时只能靠 prompt 自然语言询问,没有结构化暂停+恢复。

方案:

  • 工具契约 ask_user_question: { question: string, options?: string[], multiSelect?: boolean }
  • agent-repl 捕获到该工具调用时:暂停 loop → 在 REPL 渲染问题 → @inquirer/prompts 收集答案 → 作为 tool result 回填
  • 非交互模式(--headless / WS gateway):立即返回 error "user_not_reachable",让 agent 自行决策
  • slot-filler.js 既有逻辑重构为该工具的 handler

Phase 2: Skill 模板增强

影响: MEDIUM | 工作量: LOW | 预计测试: ~20 tests

2.2.1 $ARGUMENTS 占位符

差距: SKILL.md body 是静态文本,无法动态接收参数。

方案:

  • packages/cli/src/lib/skill-md-parser.js 新增 substituteArguments(body, args):
    • $ARGUMENTS → args 原文拼接
    • $1/$2/... → args 拆分后按位置替换(shell-like)
    • 未替换占位符保留原样(不报错)
  • run_skill 工具调用时:args 字段 → substituteArguments → 注入 messages

2.2.2 Skill directory 路径注入

差距: Skill 内部引用脚本/资源时需要绝对路径,目前靠 prompt 硬写。

方案:

  • Skill 加载时 loader 记录 skillDir 绝对路径
  • 调用 run_skill 时 body 前自动 prepend 一行:Skill directory: <abs path>
  • 允许 SKILL.md 内部用相对路径如 ./scripts/foo.sh,LLM 根据 Skill directory 自行拼绝对路径

Phase 3: Subagent Registry 声明式化

影响: MEDIUM | 工作量: MEDIUM | 预计测试: ~30 tests

2.3.1 问题

src/commands/cowork.js 中 debate / compare / analyze 的 subagent role 是硬编码 if-else,新增角色要改主流程;prompt 里可用子代理的列表也是手写。

2.3.2 方案

  • 新建 packages/cli/src/lib/subagent-registry.js:
    • SUBAGENT_REGISTRY: Map<name, { shortDescription, systemPrompt, toolAllowlist, model?, maxTurns? }>
    • 内置 3 个:explorer(readonly 工具集)/ executor(全工具)/ design(前端特化,含 css_gen/html_gen)
    • buildSubagentSummaryLines(): 返回多行字符串供主 system prompt 拼接
  • spawn_sub_agent 工具 inputSchema 新增 subagent: string 字段,registry 查表注入对应 profile
  • cowork debate/compare/analyze 迁移:内部改为 spawn_sub_agent({ subagent: "executor", ... }),但对外 CLI 命令保持不变(向后兼容)

Phase 4: Turn-scoped prepareCall

影响: MEDIUM | 工作量: MEDIUM | 预计测试: ~25 tests

2.4.1 问题

agent-repl.js 启动时构建一次 system prompt 就固化到 messages[0],运行中无法:

  • 切模型(per-call override)
  • 热更新 skill 列表
  • 动态注入 sandbox / cwd / git status 等易变上下文

2.4.2 方案

  • agent-core.js agentLoop 每次 iteration 前调用 prepareCall({ messages, turn, session })
    • 返回 { systemOverride?, modelOverride?, providerOptions?, toolsFilter? }
    • 默认实现:注入最新 cwd、git status 摘要、可见 skill 列表
  • REPL /model <id> 命令改为修改 session.modelOverride,下一 turn 生效
  • 向后兼容:未提供 prepareCall 时退化到现有静态 system prompt

Phase 5: Provider-options 三层深合并

影响: MEDIUM | 工作量: LOW | 预计测试: ~15 tests

2.5.1 问题

llm-manager.resolveCategory() 只决定 { provider, model }thinking / reasoning_effort / maxTokens 等 provider-specific 参数无法分层配置,导致 SKILL.md 里要针对每个 provider 重复写。

2.5.2 方案

  • 新增 llm-manager._mergeProviderOptions(provider, modelId, callOverrides):
    1. Layer 1 provider defaults: llm-config.json:providers.<name>.defaults
    2. Layer 2 modelId 推断: getAnthropicSettings(modelId) / getOpenAISettings(modelId) — 按模型自动启用 thinking
    3. Layer 3 per-call overrides: 调用方显式传入
    4. 深合并(非浅 spread),数组替换、对象递归
  • chat() 接入:resolveCategory 返回新增 options 字段透传给 provider adapter
  • SKILL.md modelHints 扩展 providerOptions 字段,由 category routing 统一处理

3. 用户文档(面向最终用户)

3.1 新增 CLI 能力

bash
# web_fetch:agent 内部自动调用,无直接 CLI(既有 browse 命令不变)

# todo_write:agent 维护,用户可查看
chainlesschain agent
> /todo                         # 显示当前 session TODO
> /todo clear                   # 清空

# ask_user_question:agent 自动触发,用户交互式回答

# Skill 参数
chainlesschain skill run my-skill "arg1 arg2"   # $ARGUMENTS = "arg1 arg2", $1=arg1, $2=arg2

# Subagent 显式指定
chainlesschain cowork analyze ./src --subagent explorer
chainlesschain cowork debate ./foo.js --subagent design

# 扩展思考(Anthropic;其它 provider 自动忽略)
chainlesschain agent -p "..." --think                 # 默认强度(--think hard|ultra 指定强度)
chainlesschain agent -p "..." --ultrathink            # = --think ultra
chainlesschain agent -p "..." --think --thinking-budget 8000   # legacy Claude 思考 token 预算

# 多模态 / 图像输入(headless;可重复 --image;png/jpg/jpeg/gif/webp)
chainlesschain agent --image shot.png -p "图里是什么?" --provider volcengine --model doubao-seed-1-6-251015

# 自动识别消息里的图片路径(Claude-Code 平价;无需 --image)
echo "描述 ./shot.png" | chainlesschain agent --input-format stream-json --output-format stream-json

# web_search:agent 内置可插拔搜索工具(tavily/brave/bocha/千帆 keyed + 免 key DuckDuckGo/百度)

扩展思考真相源:思考决策集中在 agent-core _anthropicThinkingParams,按 model 自动择一—— 自适应思考模型(Opus 4.6/4.7/4.8、Sonnet 4.6)走 output_config.effort,legacy 模型(Sonnet 4.5、 Opus 4.0–4.5)走 enabled + budget_tokens(--thinking-budget),其余(如 Haiku)关闭。

多模态转换:内部统一成 OpenAI 形状 image_url,再按 provider 转换——OpenAI 兼容 (volcengine/doubao 等)透传、ollama 转 {content, images:[base64]}、anthropic 转 image content block。

图片路径自动识别(Claude-Code 平价):除显式 --image,消息文本里写一个磁盘真实存在的 本地图片路径会被自动当视觉输入读图——detectImagePaths 扫描受支持扩展名 + 存在性,支持 C:\… / C:/… / Git-Bash /c/… / ~/… / IDE 拖拽 file:///C:/…(含 %20),剥离路径文本, 跳过 http(s)/data:;命中后该回合切视觉模型resolveVisionLlmllm.visionModel 或默认 doubao-seed-2-0-lite-260215,只换 model)。生效于 headless stream-json / 交互 REPL / VS Code+JetBrains 面板(面板经 cc agent --input-format stream-json 驱动,零改插件)。CC_AUTO_IMAGE=0 关闭。

3.2 配置项

.chainlesschain/config.json 新增:

json
{
  "webFetch": {
    "enabled": true,
    "allowedDomains": ["*"],
    "maxBytes": 2000000,
    "timeout": 15000
  },
  "todos": {
    "persist": true,
    "maxPerSession": 50
  },
  "llm": {
    "providerOptions": {
      "anthropic": { "thinking": { "type": "enabled", "budgetTokens": 8000 } },
      "openai":    { "reasoning_effort": "medium" }
    }
  }
}

3.3 SKILL.md 增强示例

markdown
---
name: quick-summarize
description: 总结 $ARGUMENTS 指定的文件
---

# 总结任务

Skill directory 下有辅助脚本,直接调用:

\`\`\`bash
node ./scripts/extract.js $1
\`\`\`

用户请求: $ARGUMENTS

4. 实施节奏与里程碑

Phase工作量依赖预计测试优先级
Phase 1: 三工具补齐~3 天~60P0
Phase 2: Skill 增强~1 天~20P1
Phase 3: Subagent Registry~2 天Phase 1(spawn_sub_agent 扩字段)~30P1
Phase 4: prepareCall~2 天~25P2
Phase 5: Provider-options~1 天~15P2
合计~9 天~150 tests

4.1 验收标准

  • [x] Phase 1:agent 可调用 3 个新工具,headless 模式下 ask_user_question 优雅降级 — 落地于 packages/cli/src/runtime/agent-core.js(web_fetch / todo_write / ask_user_question)
  • [x] Phase 2:skill run foo "bar baz" 正确替换 $ARGUMENTS / $1 / $2 — 落地于 packages/cli/src/lib/skill-loader.js(substituteArguments)
  • [x] Phase 3:cowork 3 命令全部走 registry,新增 subagent 只需改一个文件 — 落地于 packages/cli/src/lib/sub-agent-profiles.js(SUBAGENT_REGISTRY)
  • [x] Phase 4:REPL 运行中 /model 切换立即生效,不需要重启 session — 落地于 packages/cli/src/repl/agent-repl.js + turn-context.js(prepareCall turn-scoped context)
  • [x] Phase 5:SKILL.md 同一份 providerOptions 在 anthropic / openai 下均能透传 — 落地于 packages/cli/src/lib/provider-options.js(mergeProviderOptions 三层深合并)
  • [x] 所有新增代码使用 _deps 注入模式,Vitest 测试在 forks pool 通过 — 158 tests pass
  • [x] 契约更新同步 coding-agent-contract-shared.cjs + coding-agent-policy.cjs,遵循 §83 canonical descriptor 规范

4.2 不做的事

  • 不引入 Bun:保持 Node 18+ 兼容
  • 不引入 Vercel AI SDK:既有 llm-manager 架构稳定,替换成本过高
  • 不引入 Ultracite/oxlint:现有 ESLint 工作良好,性能非瓶颈(附录单独评估)
  • 不引入 Durable Workflow:sub-runtime-pool + session 持久化已覆盖断线恢复

5. 风险与规避

风险影响规避
web_fetch 任意 URL 访问 → SSRF / 信息泄漏HIGH白名单域名 + Plan Mode 审批 + 默认禁用内网段
todo_write 状态在 crash 时丢失MEDIUMpersist: true 时写入 session record,crash recover 时重放
ask_user_question 在 WS gateway 场景阻塞MEDIUM超时 60s 自动返回 error,agent fallback 到自行决策
prepareCall 破坏 Hermes Phase 4 "冻结提示词" 约定HIGH只注入增量 context(cwd/git/skills),system prompt 主体仍冻结
Subagent Registry 与既有 auto sub-agent 冲突LOWregistry 为 opt-in,未指定 subagent 时保持现有行为

6. 附录

6.1 Open-Agents 源码引用

  • packages/agent/open-harness-agent.ts:1-145 — ToolLoopAgent 主入口
  • packages/agent/subagents/registry.ts — SUBAGENT_REGISTRY 定义
  • packages/agent/skills/loader.ts — extractSkillBody / substituteArguments / injectSkillDirectory
  • packages/agent/models.ts:1-202 — mergeProviderOptions + getAnthropicSettings
  • packages/agent/tools/{web_fetch,todo,ask-user-question}.ts — 三工具实现

6.2 Ultracite 评估(附录,不在本方案范围)

Ultracite = oxlint(Rust 实现 ESLint)+ oxfmt(Rust 实现 Prettier),比 ESLint 快 50–100 倍。CLI package 当前 lint 耗时 < 10s,非瓶颈;但 desktop-app-vue 全量 lint ~60s,可单独立项评估迁移 ROI。

6.3 未来扩展

  • Durable Resume:WS server 长任务断线恢复(当前 sub-runtime-pool 已支持,补文档即可)
  • Agent Registry 跨进程:registry 扩展到 desktop-app-vue cowork 模块,CLI / 桌面共享 subagent 定义
  • Skill Frontmatter 扩展:借鉴 open-agents modelHints.providerOptions,让 Skill 定义即配置

维护者: 开发团队 关联 Memory: 待补齐后写入 .claude/memory/open_agents_parity.md

附录:规范章节补全(v5.0.3.108)

本文为系统设计子文档。为对齐项目文档标准结构,下列章节以 见正文 指引或简述方式补齐若干视角,不重复正文细节。

1. 概述

见正文「模块概述 / 功能描述」。Open-Agents 对标补齐方案(Open-Agents Parity v1.0):对标 Open-Agents 补齐。

2. 核心特性

Open-Agents 平价 / 内置工具 / Sub-Agent / prepareCall。

3. 系统架构

见正文「架构设计」。

4. 系统定位

ChainlessChain 的「Open-Agents 对标补齐方案」。

5. 核心功能

见正文模块概述与各节。

6. 技术架构

见正文实现章节。

7. 系统特点

见正文(状态 / 版本 / 特性)。

8. 应用场景

见正文应用场景 / 背景。

9. 竞品对比

见正文对比(如有)。

10. 配置参考

见正文配置 / 参数章节。

11. 性能指标

见正文性能 / 指标章节。

12. 测试覆盖

见正文测试章节。

13. 安全考虑

见正文安全 / 权限章节。

14. 故障排除

见正文故障 / 已知限制章节。

15. 关键文件

见正文实现位置 / 关键文件章节。

16. 使用示例

见正文使用 / API 示例。

17. 相关文档

系统设计主文档docs-site 对应功能页。

基于 MIT 许可发布