旧会话越聊越笨,新会话又得重讲?我给 Matt Pocock Skill 炼了套《影分身之术》:本体想清楚,分身写代码,完事回来汇报 ——大厂 Agent 开发技术分享

发布于

![图片预览](http://pic.zhso.org/2026/08/19/dbb3a872f1b2.png)

## 先跟大家聊下背景

平时写代码,不管你用 Codex 、Cursor 、Claude Code 还是别的 Agent ,基本都是在一个会话里聊问题、聊需求、聊项目背景。你告诉它怎么做,有什么注意点,把你知道的上下文都交给它。等双方把需求和方案确认下来,再让它开始写代码、做实施。

一般都是这样一个流程。

这样聊出来的内容其实非常有价值。里面有项目背景、有用户真正想要什么、有已经做过的取舍,也有那些看起来没写进需求、但做错了就会跑偏的细节。

问题是,后面还一直在同一个会话里写代码。文件内容、搜索结果、命令输出、测试日志会不断往里塞,会话越来越长,也会不断压缩。每压一次,前面聊过的东西都会占一部分上下文,剩余空间就越来越小。

打个比方,最开始可能还有 100%,压缩以后可能 80%、60%,最后只剩百分之十几。这个时候聊不了几句话、做不了多少事,又得压缩,很费时间。上下文太多,模型速度会越来越慢,效果也可能越来越差。

但你又不太敢直接开新会话。因为前面已经把需求和上下文都对齐了,新会话还得重新读仓库、理解现有代码,再把这些内容和任务对应起来。

怕丢上下文,又不太敢开新会话。这就是我想解决的问题。

## 第一版:先把共识编成一份 Goal

我是在 Matt Pocock Skills 的基础上做这个改良的。

前半段还是它原来的思路:有想法或需求,先 Grill ,把问题和细节聊清楚;然后运行 `/to-spec`,把双方确认的内容整理成一份 Spec 。用户确认以后,我会打一个状态:`SPEC READY`。

它代表这份 Spec 已经和用户达成共识,可以开始实施了。
```text
想法 / 需求

Grill

/to-spec

用户确认 → SPEC READY
```

我最早做的改进,是在 `SPEC READY` 以后用 `/to-goal` 把这份已经确认的 Spec 编成 Goal 。Goal 里面会带着当前状态、执行顺序、完成标准、约束和验证要求。然后把它放进一个干净的新会话,或者放进另一个 Agent 里执行。执行完,再把结果带回原来的主会话。

这样做的原因很简单:聊需求和写代码,本来就是两类工作。主会话负责把事情想清楚、把控细节和方案;新会话围绕已经确认的 Goal 去读代码、做实施。代码执行产生的大量中间上下文,不再把主会话塞得越来越挤。

Goal 还有两个很实际的好处。第一,它不绑 Codex ,任意 agent 里都可以去跑,你拿去 Cursor 、Claude Code 、Pi ,甚至别的 Agent 里也可以继续实施。第二,大任务可以拆成多个 Goal ,每个 Goal 你还可以放到每一个独立 Worktree 里并行去跑,来帮你进行提速。
大概的流程:
```text
SPEC READY

Goal A → Worktree A → Agent A
Goal B → Worktree B → Agent B
Goal C → Worktree C → Agent C
```

不过用了以后,我后面想到了一个问题。Goal 能把已经确认的目标、范围和完成标准带过去,却不能把仓库探索的相关上下文塞过去。

所以新的执行会话拿到 Goal 以后,还是要重新读一遍仓库:先看项目说明和当前代码,找到相关文件,理解现有实现,再把这些代码和 Goal 对上。这个过程会重新消耗一遍 token 和时间。而这些仓库上下文,主会话在前面讨论方案时其实已经读过、理解过了,这部分其实会造成一些额外的开销。

这就是我后面继续做 Fork 的直接原因。

## 第二版:能继承上下文,就直接 Fork

有些任务刚刚在当前会话里讨论完成。主会话已经读过仓库、理解了现有代码,也和用户确认了最终 Spec 。这个时候再开一个完全干净的会话,从头读取同一份仓库上下文,确实有点重复,会产生额外开销。

所以这类任务我就直接从当前会话 Fork 一个新会话。

Fork 出来的会话会继承前面的讨论和已经建立好的仓库理解。它知道相关代码在哪里、为什么这样改,也知道用户的真实意图,可以直接根据最终的 `SPEC READY` 开始实施。

还有一个很实际的好处:Fork 前后的上下文前缀是一致的,可以继续利用已有的上下文缓存。前面读取仓库、分析代码、讨论方案所形成的缓存不需要全部重新计算,启动更直接,token 、时间和成本也会更低。

所以我又加了 `/spec-executor`:Fork 完以后,在这个新会话里直接运行它。它会按最新的 `SPEC READY` 去开发、验证和 Review ,最后输出一张 `SPEC EXECUTION RECEIPT`。

这张 Receipt 会把改了什么、验了什么、哪些完成标准通过了、还有什么没做,写清楚。然后把它复制回主会话,主会话就能知道这个任务到底做到什么程度。

这版省掉了新会话重新读取仓库、重新建立任务理解的成本,但还需要手动 Fork 、手动运行命令、手动复制 Receipt 。

都已经用 Agent 了,还在两个窗口之间搬文字。加上最近 claude code 出了个 session 间发送会话的功能嘛,我给 codex 也做了套这个功能,来自动化这部分人工的流程,于是就有了下面的第三版。

## 第三版:让 Fork 自己回来汇报

所以后面又做了 [Codex Task Messenger](https://github.com/tt-a1i/codex-task-messenger) 和 `/execute-spec-in-fork`。

现在主会话里已经 `SPEC READY` 以后,直接调用 `/execute-spec-in-fork`。主会话会自动创建 Fork ,给子会话发送任务;子会话在 Fork 里调用 `/spec-executor` 去实施;做完以后,Task Messenger 再把 Receipt 主动回传给主会话。

如果主会话检查出问题,就把问题发回同一个 Fork 继续改。改完再回传,直到没问题,再把这个 Fork 归档。
```text
主会话:需求、方案、决策、检查结果

Fork 会话:开发、测试、Review 、Receipt

Task Messenger:自动把结果送回主会话
```

我现场演示过一个任务:Fork 出去的会话跑了 56 分钟,跑完以后把 Receipt 自动回传,主会话检查完成后归档。以前手动做的 Fork 、派工、复制结果和收尾,现在由这套流程自己完成。

这里 Fork 和 Goal 不是谁替代谁,而是两套不同的上下文策略:
- 当前会话刚读完仓库、谈清需求,而且一次能做完:Fork ,继承仓库理解并利用上下文缓存;
- 跨人、跨天、跨引擎、多个 Worktree 并行,或者当前历史已经很乱:Goal ,把任务压成一份可独立执行的合同。

一句大白话:能顺着刚才的讨论接着干,就 Fork ;需要搬运、并行或者换引擎,就 Goal 。

## 另外一些简单但实用的改动

除了主流程,我还改了一些日常会用到的东西。

原来的 Grill 一轮只问一个问题,复杂需求可能要来回二三十次。我把三个 Grill 都改成按依赖批量提问:当前能一起回答的问题放在同一轮,回答完再展开下一层。实际用下来,经常两三轮就能把主要分支聊完。

我也加了一些带类型的 Emoji ,用来区分范围、风险、取舍、建议和待确认项。不止是为了装饰,主要是长文本里更容易找到重点。

上游最近增加的几个 Skill 我也同步了:
- `/research`:让子 Agent 去查官方文档、源码和一手资料,最后留一份带引用的研究文档;
- `/wizard`:把登录后台、配置 Token 、写入 Secret 这类必须人参与的流程做成交互式脚本,之后还能分享给同事复用;
- `/wait-what`:Agent 又开始说黑话时,让它用当前项目的语境把刚才那件事重新讲明白。

## 最后

现在这套方法其实很简单:主会话负责想清楚,执行会话负责写代码,Receipt 负责把结果和证据带回来。

如果任务还说不清什么叫做完,就继续聊;如果已经 `SPEC READY`,再决定是 Fork 还是 Goal 。

项目和资料:
- 改良版仓库:[tt-a1i/matt-skills-with-to-goal](https://github.com/tt-a1i/matt-skills-with-to-goal)
- GitHub 主页:[tt-a1i](https://github.com/tt-a1i)
- B 站视频:[《 Agent 开发焚诀 - 字节周会技术分享》](https://www.bilibili.com/video/BV1UXgK64E4J/)

大家感兴趣可以去视频里看,这个视频的反响还蛮好的,发布 3 天已经有 1000+收藏了,具体命令、完整演示,ppt 讲解,以及 Task Messenger 怎么自动回传,B 站视频讲的很清楚。

---

原文链接:[点击查看](https://www.v2ex.com/t/1235560)

评论

暂无评论。

0.044125s