受控样本同任务请求与回复对比
受控样本同任务请求与回复对比
样本说明
这次不再使用之前的 Kiro 样本,而是只使用你后来专门控制变量后跑出来的两个真实 session。
样本如下:
OpenCodesession:ses_2756a886affeEuvyDTX7mgv598OpenCode标题:Claude Code MCP与skill调用链路分析OpenCode落盘: opencode.dbClaude Codesession: 55a6d062-ad55-44a8-b7a1-21b372f21ff9.jsonl
分析边界也严格收窄:
- 只看第一条同任务 prompt 的首轮完整执行
- 不把后面你追加的
drawio请求混进来 - 不把
/exit、local-command-caveat之类本地命令元消息算进同任务主线
先给结论
这次样本比之前更干净,也更能说明问题。
同一个分析型任务,在这两个 session 里都表现为:
- 一条用户 prompt
- 多次中间工具调用
- 一条最终总结答复
但落盘主形态仍然不同:
OpenCode更像一条 user message + 多条 assistant message(part 化) + 一条最终总结Claude Code更像一条 user event + 多个 assistant text/thinking/tool_use + 多个 user(tool_result) + 一条最终 assistant text
也就是说,这次控制变量之后,差异没有消失,只是变得更精确了:
两边都能较清晰地重建完整请求和完整回复,但 OpenCode 仍然更偏 message/part 数据库,Claude Code 仍然更偏事件流 transcript。
元数据对比
OpenCode 记录到的元数据
首条用户消息:
{
"role": "user",
"time": { "created": 1776146544563 },
"agent": "build",
"model": {
"providerID": "modelscope",
"modelID": "ZhipuAI/GLM-5"
}
}首轮 assistant message:
{
"role": "assistant",
"mode": "build",
"agent": "build",
"providerID": "modelscope",
"modelID": "ZhipuAI/GLM-5",
"finish": "tool-calls"
}Claude Code 记录到的元数据
首条用户 event:
{
"type": "user",
"entrypoint": "cli",
"cwd": "/Users/util6/fork-code/claude-code-rev",
"sessionId": "55a6d062-ad55-44a8-b7a1-21b372f21ff9",
"version": "2.1.92",
"gitBranch": "claude-code-rev-learn"
}首个 assistant message:
{
"type": "assistant",
"message": {
"role": "assistant",
"model": "glm-5.1:cloud",
"content": [
{ "type": "thinking", "thinking": "..." }
]
}
}这里要明确一点:
你主观上是按“同一个模型”来做控制变量的,但从这两边的实际落盘元数据看,记录下来的模型标识并不完全一致:
OpenCode:modelscope / ZhipuAI/GLM-5Claude Code:glm-5.1:cloud
所以这次文档会按“同任务、同类模型意图、同仓库、同 prompt”来对比,但不会在文档里写成“本地元数据完全证明是同一 model id”。
同一条 prompt:两边的完整请求
这次两边的用户 prompt 在语义上是同一条任务。
OpenCode 的真实请求
当前仓库是claude code源码库,结合https://www.waylandz.com/diagrams/claude-code-architecture.html这张架构图,帮我分析其MCP和skill的调用时机和链路Claude Code 的真实请求
当前仓库是claude code源码库,结合https://www.waylandz.com/diagrams/claude-code-architecture.html这张架构图,帮我分析其MCP和skill的调用时机和链路这次和上一个 Kiro 样本最大的不同就在这里:
- 没有 system reminder 掺进主线
- 没有后续用户追问掺进第一轮
- 就是一条干净的分析型任务 prompt
因此这次更适合直接比较“同一任务的完整请求和完整回复”。
OpenCode:这条任务的完整回复长什么样
OpenCode 这次的会话结构非常清楚:
- 1 条 user text
- 8 条 assistant reasoning
- 19 个 tool parts
- 1 条最终 assistant text
OpenCode 的 reasoning 链
它的中间 reasoning 不是一条,而是一串逐步推进:
- 先说要获取架构图并探索 MCP/skill 代码
- 再说已经拿到架构图内容和若干路径,准备读关键文件
- 再继续收缩到
MCPTool.ts、SkillTool.ts、tools.ts、toolOrchestration.ts - 再继续下探
toolExecution.ts、MCP client - 最后汇总并输出总结
这些 reasoning 在落盘里都是 assistant part.type = reasoning。
OpenCode 的 tool 链
本次一共记录了 19 个 tool part,顺序如下:
1. webfetch
2. glob
3. glob
4. read
5. read
6. read
7. glob
8. read
9. read
10. grep
11. read
12. read
13. glob
14. read
15. grep
16. read
17. read
18. read
19. read其中最关键的几类是:
webfetch:抓架构图网页glob:搜mcp*/skill*/src/tools/**/*.tsread:读MCPTool.ts、SkillTool.ts、toolOrchestration.ts、toolExecution.ts、client.ts、commands.tsgrep:补mcpClient、toolExecution等交叉引用
也就是说,OpenCode 这次是一个很标准的:
先抓外部图,再扫本地路径,再精读核心文件,再汇总。
OpenCode 的最终完整回复
最终 assistant 文本是直接落在 session 里的,开头如下:
基于架构图和代码分析,以下是 **MCP 和 Skill 的调用时机和链路**:正文结构非常完整,包含:
- 调用时机
- MCP 调用链路
- Skill 调用链路
- 核心文件映射
- 四层扩展体系交互
它的最终总结是一个标准的用户可读大答案,而不是单纯工具日志。
这说明:
在这个受控样本里,OpenCode 的最终回复是很容易直接从数据库里提取出来的。
Claude Code:这条任务的完整回复长什么样
Claude Code 这次的样本也比之前更清楚,因为这个 session 的首轮执行里确实包含了:
- assistant thinking
- assistant text
- assistant tool_use
- user(tool_result)
- 最终 assistant text
Claude Code 的主线结构
首轮执行主线大致是:
- assistant thinking:先说要抓架构图并探索代码
- assistant text:告诉用户“让我获取架构图,并同时探究 MCP 和 Skill 的代码库”
WebFetch- 两个
Agent异步子任务 TaskCreateTaskUpdate- 多个
Read - 多个对应的
tool_result - 最终 assistant text:完整分析
Claude Code 的 tool 形态
和 OpenCode 不同,这里 tool 不是被挂成 assistant part.type=tool,而是更像事件流:
- assistant 发出
tool_use - 随后 user event 里写入对应
tool_result
例如:
{"type":"tool_use","name":"WebFetch", ...}
{"type":"user","message":{"content":[{"type":"tool_result", ...}]}}以及:
{"type":"tool_use","name":"Agent", ...}
{"type":"user","message":{"content":[{"type":"tool_result","content":"Async agent launched successfully..."}]}}这次样本里甚至能清楚看到:
- 异步 Explore agent 启动成功
TaskCreateTaskUpdateRead某些文件失败或超长
这说明 Claude Code 本地 transcript 的“完整回复”里,执行细节暴露得比 OpenCode 更直。
Claude Code 的最终完整回复
这个 session 的最终总结文本真实存在,而且比较完整。
开头如下:
根据架构图和源码分析,以下是 MCP 和 Skill 的调用时机和链路的完整分析:正文结构同样非常完整,包含:
- MCP Server 初始化阶段
- MCP Tool 调用时机
- MCP 完整链路图
- Skill 注册发现
- Skill 触发方式
- Skill 完整链路图
- MCP 与 Skill 差异对比
- 四层扩展体系总结
所以这次很重要的修正是:
在这个更干净的受控样本里,Claude Code 也能清晰地看到完整请求和完整回复,不只是工具事件流。
这次样本和上次样本的差别
这也是为什么你会对上一个对比不满意。
上一个 Kiro 样本的问题在于:
OpenCode那边混入了 system reminder 和多轮追问Claude Code那边没有同任务真样本,只能模拟
所以那次对比,更多是在比较“两个系统的典型存储风格”。
而这次不同:
- 两边都是真实同任务样本
- 两边都能直接看到 prompt
- 两边都能直接看到最终分析结论
因此这次更适合回答:
当任务控制得足够严格时,两边的真实请求和真实回复到底长什么样。
这次样本下的真正结论
1. 两边都能清晰看到完整请求
这次两边都几乎是同一条用户 prompt,没什么争议。
2. 两边都能清晰看到完整回复
这次和上次最大的修正就在这:
OpenCode可以看到完整最终总结Claude Code也可以看到完整最终总结
所以不能再说成:
OpenCode才能看到完整回复Claude Code只能看到执行日志
这个结论在这个受控样本下是不成立的。
3. 真正的差别在“中间层怎么落盘”
两边真正不同的是中间过程:
OpenCode
- reasoning 单独存成 assistant part
- tool 调用单独存成 assistant part
- 最终 text 单独存成 assistant part
所以它更像:
结构化 message/part 会话数据库
Claude Code
- thinking 是 assistant content block
- tool_use 是 assistant content block
- tool_result 常落在后续 user event 里
- 最终总结再落成 assistant text
所以它更像:
线性事件 transcript
4. 这次受控样本下,最准确的对比句
不是:
OpenCode 能看完整回复,Claude Code 看不到
而是:
两边都能看完整请求和完整回复;只是 OpenCode 更像“分层会话记录”,Claude Code 更像“线性事件记录”。
同一任务下,两边分别怎么做的
OpenCode 的做法
用户 prompt
→ assistant reasoning
→ webfetch 架构图
→ glob 搜索 mcp/skill 文件
→ read 核心文件
→ grep 补交叉引用
→ assistant 最终总结落盘形态:
message(user)
message(assistant) + reasoning/tool
message(assistant) + reasoning/tool
...
message(assistant) + textClaude Code 的做法
用户 prompt
→ assistant thinking/text
→ WebFetch
→ Agent 异步探索
→ TaskCreate / TaskUpdate
→ Read 多个核心文件
→ tool_result 回填
→ assistant 最终总结落盘形态:
user
assistant(thinking/text/tool_use)
user(tool_result)
assistant(tool_use)
user(tool_result)
...
assistant(final text)最终结论
这次真正控制变量之后,结论应该修正为:
- 这两个系统在“同任务、同 prompt”的场景下,都能本地还原完整请求和完整回复。
OpenCode的优势不是“只有它能看到完整回复”,而是它把 reasoning、tool、text 拆得更清楚,更适合程序化分析。Claude Code的优势不是“只有执行日志”,而是它把整个过程串成了一条线性 transcript,更适合顺序回看。
最后压成一句:
在受控样本下,OpenCode 更像结构化会话数据库,Claude Code 更像线性会话日志;两边都能看到完整任务,只是中间层的组织方式不同。