CodeGraph 互动式 A/B 实测:直接在主会话作答,还是委派给 Explore 子代理?
本篇基于 CodeGraph 仓库中的实测报告 answer-directly-vs-explore-agent.md,拆解一个对 Claude Code 用户很关键的问题:当 agent 回答"X 是怎么工作的"这类结构性问题时,在主会话中直接调用 CodeGraph 作答,与把探索委派给一个一次性 Explore 子代理(用子转录吸收文件读取、保持主上下文精简),哪种方式更优?读完本篇,你将掌握:互动式 A/B 实验的完整方法论(为什么必须用 tmux 驱动 TUI 而不是 claude -p)、主会话上下文在 16 倍仓库规模下为何保持 ~50k 不变的预算机制(explore 输出的分层预算上限),以及这条结论如何直接改写了 CodeGraph 下发给 agent 的指令文案。
核心问题与结论先行
报告要回答的问题非常具体:直接在主会话用 CodeGraph 回答"how does X work?",会不会把主会话上下文撑爆?Claude Code 是不是应该把这类探索委派给 Explore 子代理(子代理在独立转录里读文件,主上下文因此保持精简)?更关键的是:当仓库规模远超 Excalidraw 时,结论会不会反转?
短答案是:不会反转。 有了 CodeGraph,主会话上下文大致是规模不变的(~50k)——因为检索是定向的、explore 的返回载荷有预算上限,仓库大 16 倍它也不会膨胀。直接作答在每一个规模上都赢:主上下文与委派路径相当甚至更精简、文件读取为 0、token 少约 28%。"为卫生而委派"的优势即使在大代码库上也只是边际性的。
重要警示:本报告的 token 数字未经复核(2026-08-05 标记)。该实验早于
parse-run.mjs的result.usage修复(commit04c0f8e),其"少 28% token"很可能取自一个只报告最后一个回合用量的字段——详见 call-sequence-analysis.md 中的踩坑记录。该误差会低估回合数更多的那一臂,因此如果委派臂跑得更长,真实差距大于 28%;如果两臂回合数相近,则数字大致正确。原始日志已丢失,无法重新推导——token 数字应视为指示性,而回合数、读取数、主上下文这些不依赖该字段的结论是可靠的。
实验方法论:为什么必须用互动式 TUI
方法学细节决定了这份报告的可信度,值得逐条拆解:
- 测试框架: 通过 itrun.sh(tmux)驱动的互动式 Claude Code TUI,而不是 headless 的
claude -p。这一点至关重要:headless 模式派生 0 个 Explore 子代理,根本无法测量委派行为;只有互动 TUI 能复现用户实际看到的行为。脚本头部注释写得很直白:"headless print-mode picks the general-purpose subagent, while real interactive sessions delegate to the Explore subagent (or drive codegraph from the main thread). Only the interactive TUI reproduces the behavior users actually see." - 两臂(Arms):
WITH= MCP 配置里启用 CodeGraph;WITHOUT= 空 MCP 配置(--strict-mcp-config)。 - 模型:
opus,每臂 n = 3。主线程与子代理的转录都被解析(parse-session.mjs),Read/Bash 次数在主线程 + 所有子代理之间求和。 - 仓库: Excalidraw(643 文件,中等规模)与 VS Code(约 10.7k 文件,大规模——约为 Excalidraw 的 16 倍)。
- 构建版本: 0.9.4。日期: 2026-05-24。
- 指标定义: "主会话上下文"指 TUI 上报的
Context X/Y中主线程的值(子代理上下文不计入);"billable tokens" = 逐回合 assistant 用量求和(input + output + cache read + cache creation)。
从源码看,parse-session.mjs 的做法与报告完全对应:它读取 Claude Code 写入 ~/.claude/projects/<escaped-cwd>/ 的 session JSONL,tally() 函数统计主转录中每个 tool_use 块,子代理转录则从 <session>/subagents/*.jsonl 汇总——这正是"reads/bash 在 main + sub-agents 上求和"的实现。sumTokens() 按回合累加 output_tokens、input_tokens + cache_creation_input_tokens(新鲜输入)与 cache_read_input_tokens,最后以 gen + fresh 作为 billable 近似值,与报告"逐回合求和"的定义一致。
itrun.sh 本身也体现了互动式测量的工程细节:它通过 tmux send-keys 输入 prompt 并做"输入验证"(确认 prompt 前 24 个字符真的落进输入框),再按内容稳定性而非 spinner 字符串判断 agent 完成——因为某些模型流式输出最终答案时不渲染任何忙碌指示符,短阈值的中断判定会把答案截断。
结果一:Excalidraw(643 文件,中等规模)
问题:"How does Excalidraw render and update canvas elements?"
| 指标 | WITH codegraph | WITHOUT |
|---|---|---|
| Explore 子代理派生数 | 0 / 0 / 0 | 0 / 1 / 1(3 次中 2 次委派) |
| 主会话上下文 | 51k / 49k / 50k(~50k) | 48k / 34k / 26k(~36k) |
| 总工具调用 | 4 / 4 / 4 | 16 / 55 / 37 |
| Reads(主+子) | 0 / 0 / 0 | 6 / 25 / 16 |
| billable tokens | ~127k | ~175k |
观察:没有 CodeGraph 时,Claude Code 在 3 次中的 2 次选择派生 Explore 子代理;派生与否直接决定了主上下文落在 26k 还是 48k——委派路径的主上下文收益是真实存在的,但代价是 16–55 次工具调用和 6–25 次文件读取。
结果二:VS Code(约 10.7k 文件,约为 Excalidraw 的 16 倍)
问题:"How does the extension host communicate with the main process?"
| 指标 | WITH codegraph | WITHOUT |
|---|---|---|
| 主会话上下文 | 47k / 43k / 50k(~47k) | 54k / 29k / 31k(~38k) |
| Explore 子代理 | 0 / 0 / 0 | 0 / 1 / 1(2/3 委派) |
| codegraph 调用 | ~8(search + explore×2–3 + context) | 0 |
| Reads(主+子) | 0 / 1 / 0 | 6 / 26 / 19 |
| billable tokens | ~126k | ~176k |
16 倍规模的仓库,WITH 臂主上下文(~47k)与 Excalidraw(~50k)几乎一致。 这正是本报告最重要的发现。
为什么主上下文是"规模不变"的:预算上限的定向检索
报告的归因是:codegraph 的 explore 返回载荷是**有预算上限(budget-capped)且检索是定向(targeted)**的——回答一个问题只拉入相关的流/区域,不会因为仓库巨大就拉更多。因此 CodeGraph 让主会话上下文大致规模不变(~50k)。"为卫生而委派"的优势即使在大代码库上也只是边际性的——恰好与"规模上会变得重要"的预期相反。
这个归因可以在源码中得到印证。tools.ts 中定义了 ExploreOutputBudget——一个随项目规模自适应分层的输出预算("Adaptive output budget for codegraph_explore, scaled to project size"):小代码库获得更紧的总上限、更少的默认文件数、更小的单文件上限;getExploreBudget(indexedFileCount) 在每次 explore 调用时根据已索引文件数解析当前项目的预算,maxOutputChars 是总输出的硬上限,候选文件按相关性排序后按比例分摊这个预算(Split budget.maxOutputChars across ranked candidates in proportion to...)。也就是说,载荷大小由"本次问题的答案面"决定,而不是由仓库大小决定——这就是"~50k 主上下文在 643 文件与 10.7k 文件仓库上都不变"的机制来源。
报告还区分了两种"主上下文精简"路径:
- Claude Code 自己也能做到(不用 CodeGraph):委派给 Explore 子代理(主上下文 29–31k),但代价是 17–26 次文件读取和约 28% 更多的 token。
- CodeGraph 的方式更优:一个有上限的定向载荷——不委派、0 次读取。
"Explore 子代理会用 codegraph"——复现失败
报告尝试复现一个流传的设想:Explore 子代理在委派后自己也会用 codegraph(既瘦主上下文、又低工作量)。结果:跨两个仓库共 6 次 with-codegraph 运行,Claude Code 一次都没有委派——每次都直接在主会话作答。Explore 子代理路径只出现在 WITHOUT 臂(因为那一臂的 MCP 配置里没有 codegraph,子代理用的是 grep/read)。
结论:在当前指令 + codegraph 在场的前提下,Claude Code 留在主会话——"经 Explore 子代理瘦主上下文"这个最佳情形实际并不会发生;发生的是"经有上限的 codegraph 瘦主上下文",而且它更便宜。
这个行为不是偶然,而是被指令文案主动引导的。server-instructions.ts 中随 MCP initialize 下发的指令明确写着:Codegraph 本身就是预建的搜索索引,"running your own grep + read loop, or delegating the lookup to a separate file-reading sub-task/agent, repeats work codegraph already did and costs more for the same answer"——即把查找委派给独立读文件的子任务会被视为重复劳动而被劝阻。instructions-template.ts 安装到 agent 指令文件中的 ## CodeGraph 区块也强调"用 MCP 工具或 codegraph explore CLI 直接作答",并且其注释记录了测量依据:强制委派场景下,没有该区块时子代理只有约 1/9 的运行会真正加载并使用 codegraph。README 中"Agent Tool Guidance"一节进一步说明:README 明确写道 "CodeGraph only helps when queried directly, so its instructions steer agents to answer directly rather than delegate exploration to file-reading sub-agents — otherwise a sub-agent reads files regardless and CodeGraph becomes overhead."
判决与对指令文案的改写
"直接用 codegraph 作答"对 Claude Code 同样全胜——在每一个规模上。 不需要按 agent 拆分;统一的"answer directly"指令对 Claude Code 和 Codex / Cursor / opencode(这些工具没有 Explore 子代理机制,否则只能直接读文件)都是正确的。
这条结论直接驱动了 README 中 ## CodeGraph 示例块的更新:旧文案曾指示 agent "NEVER 直接调用 codegraph_explore / ALWAYS 派生一个 Explore 子代理"——那正是把 Claude Code 引向更差的路径(17–26 次读取、多 ~28% token)。当前仓库中的指令文案("answer directly"、"delegating the lookup to a separate file-reading sub-task/agent repeats work")就是这次实验的产物。
保留项:Explore 子代理 + codegraph 的组合为何暂不采纳
报告诚实地列出了唯一反方向的可能性:一个自己会用 codegraph 的 Explore 子代理,理论上能同时拿到瘦主上下文和低工作量。但报告给出三条不把它设为默认的理由:
- "answer directly" 指令在实际中阻止了委派(6 次运行 0 次委派),该路径当前根本不会发生;
- 主上下文收益是边际性的:~50k → ~30k,两者都只占 1M 窗口的几个百分点;
- 它增加一轮子代理往返。
因此结论是:值得做未来的实验,不值得设为默认。
复现与延伸阅读
本实验的原始日志已不可得(见开头警示),但仓库保留了完整的可复现工具链:
- itrun.sh:
itrun.sh <repo-path> <label> "<prompt>",tmux 驱动互动式 Claude Code 会话,要求 tmux 3.0+、已登录的claudeCLI 与配好的 codegraph MCP;输出目录由AGENT_EVAL_OUT控制(默认/tmp/agent-eval)。 - parse-session.mjs:
node scripts/agent-eval/parse-session.mjs <project-dir>,输出主/子线程工具调用统计、billable token 估算,以及 explore 之后的充分性(sufficiency)与答案取材(allocation)分析。
延伸阅读(同目录下的对照报告,共享同一方法论与 result.usage 踩坑记录):
- call-sequence-analysis.md:37 个 A/B 单元的调用序列分析,量化了
result.usage只报最后一回合的字段缺陷(commit04c0f8e修复),并给出"读取得节省不转化为墙钟时间"的归因。 - codegraph-ab-matrix.md:readings 减少 75% 而墙钟仅 ~16% 的 A/B 矩阵总表。
方法学上的三点经验(对做类似 A/B 的人)
- 测量委派行为只能用互动 TUI。 headless 模式不派生 Explore 子代理,测出来的是另一个问题。
- 指标定义必须跨主/子线程求和——否则子代理里的 25 次 Read 会直接从统计里消失(本实验 WITHOUT 臂的主力成本全在子转录里)。
- token 字段要先验证再使用。 本实验的 ~28% 差距来自一个只报末回合的字段;回合数、读取数这类计数型指标不受该缺陷影响,应作为主要判决依据。仓库后续报告在 call-sequence-analysis.md 中把"读逐回合 usage 求和,而非
result.usage"固化为了方法论规则。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00