你好,我是程序员无隅
🌈 这是我的个人主页: 无隅的主页
🌟 "技术永无止境,希望我的内容能帮到你"
最近我一直在学习一个 Coding Agent 项目。
最开始,我的学习方式很直接:遇到看不懂的模块,就让 Agent 搜索源码、梳理调用链,然后把结果讲给我。
这种方式在单次对话里很好用,但只要学习时间被拉长,问题很快就出现了。
今天刚弄清楚工具参数如何校验,过几天再问相关问题,Agent 又要重新搜索入口;上次还没有理解的地方,没有明确的继续位置;某些结论只是根据局部代码推测出来的,却可能在后续对话中被当成项目事实。
我逐渐发现:长期学习一个项目,真正困难的不是让 Agent 读懂一次源码,而是让多次学习之间能够连接起来。
为了解决这个问题,我写了一个项目学习 Skill。它不负责替我生成一份庞大的项目说明书,而是约束 Agent 如何定位问题、阅读源码、组织讲解,并把经过验证的知识沉淀下来。
本文的核心观点是:项目学习 Skill 不是一个自动总结器,而是一套学习工作流。问题驱动决定本次学什么,最小源码链控制阅读范围,分层记录保存学习状态,知识边界保证结论可信。
一、普通 AI 问答为什么不适合长期学习项目
在一次独立对话中,Agent 的源码分析能力通常已经足够强。
我们可以问它某个函数的作用,也可以让它从入口追到下游,甚至可以让它对比两个模块的设计差异。真正的问题出现在第二次、第三次以及更多次学习之后。
1. 每次对话都容易重新开始
假设我第一次学习了工具注册,第二次学习参数校验,第三次想继续研究权限判断。
如果没有统一的学习记录,Agent 并不知道哪些内容已经理解、哪些只是看过、哪些问题上次还没有解决。为了保证回答准确,它只能重新搜索相关文件,再重建一遍上下文。
于是,项目学习很容易退化成下面的循环:
- 提出一个源码问题。
- Agent 在项目中重新搜索。
- Agent 给出一份当前对话中的解释。
- 对话结束,学习状态没有被结构化保存。
- 下次遇到相邻问题,再从定位模块开始。
单次回答可能是正确的,但多次回答没有形成可以复用的学习成果。
2. 源码阅读范围容易失控
当问题比较宽泛时,Agent 很容易搜索大量文件。
例如,"工具系统是怎么工作的"可能涉及工具注册、Schema 生成、模型调用、参数解析、权限判断、并发执行和结果回传。如果一次把这些内容全部展开,得到的往往不是更完整的理解,而是一份信息密度很高的源码清单。
对于学习者来说,真正有效的方式通常是先抓住一个机制:这次只理解参数如何从模型输出走到工具执行,下次再学习权限判断或并发调度。
3. 聊天结论不等于项目事实
Agent 能根据源码进行合理推断,但"合理"不代表"已经被当前代码证明"。
如果没有明确的知识边界,下面几类内容很容易混在一起:
- 当前源码直接证明的事实。
- 根据局部代码做出的推测。
- 尚未解决的问题。
- 过去正确、现在已经失效的旧结论。
时间久了,学习笔记看起来越来越完整,可信度却可能越来越低。
所以,我需要的不是一个更长的对话记录,而是一套能够管理学习范围、进度和证据的机制。
二、项目学习 Skill 的本质是什么
Skill 不是一个新的模型,也不只是几句"请认真分析源码"的提示词。
在这个场景中,我更愿意把它理解成:
一份写给 Code Agent 的项目学习协议。
它规定了 Agent 面对不同学习请求时应该采取什么动作。
例如:
- 当我说"学习某个模块"时,先给出简短的模块地图,再聚焦一个核心机制。
- 当我提出具体问题时,先定位职责所属模块,再追回答问题所需的最小源码链。
- 当我要求深入某个函数时,从定义、调用者、输入输出和下游影响展开。
- 当我说"继续"时,读取上次的学习状态,而不是重新选择一个话题。
- 当我要求复习时,先向我提问,再根据源码纠正回答。
- 当我要求审计时,检查已有知识是否仍然与当前源码一致。
这些模式看起来不同,背后的目标却是一致的:先确定本次学习任务,再决定需要读取多少源码。
它没有强迫我按照项目目录从头学到尾,也没有提前生成一份覆盖整个仓库的教程。学习仍然从我的问题出发,只是 Agent 的行为变得更加稳定。
三、从问题出发,只追一条最小源码链
这个 Skill 最重要的设计,是把"阅读一个项目"缩小成"回答当前问题"。
假设我问:
模型生成工具参数之后,系统是怎么解析和校验的?
Agent 不需要先解释整个工具系统,也不需要把所有工具类都读一遍。它应该先从问题中提取"工具参数""解析""校验"等关键词,再判断哪个模块拥有核心职责。
随后,围绕这个问题追出一条最小链路:

这里的"最小"不是少读代码,而是只读取能够证明当前结论的代码。
一次学习通常只需要回答六个问题:
- 入口在哪里?
- 主流程经过哪些关键节点?
- 哪个函数拥有核心职责?
- 输入是什么?
- 输出会交给谁?
- 怎样验证自己的理解?
这与按照目录顺序阅读有明显区别。
| 学习方式 | 起点 | 阅读范围 | 适合解决的问题 |
|---|---|---|---|
| 目录驱动 | 文件和模块结构 | 容易逐层扩大 | 快速建立项目全貌 |
| 问题驱动 | 一个具体疑问 | 当前问题所需的最小链路 | 深入理解机制与调用关系 |
目录地图仍然有价值,但它更适合帮助我们确定位置,不应该自动变成每次学习的完整任务清单。
先用地图确定自己在哪里,再沿当前问题需要的路径向下追。
四、为什么要把学习记录拆成三层
如果把每次学习的所有内容都追加到一个 Markdown 文件里,这个文件很快就会变成另一份难以维护的聊天记录。
稳定的模块知识、一次具体问题和个人学习进度,本来就是三种不同的信息。把它们放在一起,不仅会产生大量重复,也很难判断一条内容应该在什么时候更新。
因此,这个 Skill 把学习记录拆成了三层:

第一层:模块知识
modules/<module>/knowledge.md 保存跨多次学习仍然成立的稳定事实。
它关注的是模块本身:解决什么问题、处于项目链路的什么位置、主调用链是什么、输入输出是什么,以及哪些结论已经被源码验证。
模块知识不会保存完整聊天,也不会记录我个人在哪个地方没听懂。它更像一份经过筛选的项目知识底稿。
第二层:问题专题
topics/<topic>.md 保存一次具体问题的学习过程。
它会记录原始问题、模块定位、最小源码链、当前已经理解的内容,以及仍然没有解决的疑问。
一个问题可能经过多个模块,但稳定事实只写入真正拥有该职责的模块文件。专题负责把这些模块串起来,避免相同结论在多个地方重复维护。
第三层:全局进度
progress.md 不保存大段知识,只负责索引。
它告诉 Agent:目前有哪些专题、分别处于什么状态、最近学习的是哪个问题,以及下次可以从哪里继续。
三层记录对应了三个不同的问题:
- 模块知识:这个项目现在是怎么实现的?
- 问题专题:我围绕什么问题学到了哪里?
- 全局进度:下一次应该从哪里继续?
拆开之后,Agent 不需要每次读取全部历史内容,只需要先看全局索引,再按当前问题加载相关专题和模块知识。
五、比记录知识更重要的,是标记知识边界
项目源码会变化,Agent 的理解也可能出错。
如果学习系统只负责不断追加结论,却不记录结论的证据和状态,那么它迟早会遇到和传统文档相同的问题:内容越来越多,使用者却不知道哪些仍然可信。
为此,我给学习记录划分了四种状态。
1. verified:当前源码已经直接证明
只有能在当前源码中找到明确依据的结论,才允许写入模块的稳定知识。
它还必须记录代码锚点,例如对应的文件、类或函数。锚点的价值不只是方便以后跳转,更重要的是让下一次学习能够重新校验这条结论。
2. inferred:有依据,但证据还不完整
有些判断符合当前代码结构,却没有被完整调用链或测试证明。
这类内容可以保留,但只能进入待验证区域,不能换一种肯定语气写成项目事实。
3. question:当前尚未解决
没有理解的问题不需要为了让笔记看起来完整而强行补上答案。
把它明确记录为问题,下一次才能从真正的薄弱点继续。
4. stale:曾经正确,现在已经失效
当源码变化导致旧结论不再成立时,系统不应该直接覆盖历史内容。
更稳妥的做法是保留旧结论,说明它为什么失效,再记录新的替代结论。这样既能避免继续使用过期知识,也能看见项目机制发生过怎样的变化。
这四种状态共同守住了一条边界:
聊天内容不能直接成为稳定知识,写入 verified 之前必须回到源码。
项目学习不应该追求"所有问题都有答案",而应该追求"我知道哪些已经被证明,哪些还没有"。
六、用一个真实问题跑完整个学习闭环
为了验证这套设计,我用它学习了一个具体问题:模型生成工具参数之后,系统如何处理和校验?
1. 先定位职责,而不是凭目录猜测
这个问题表面上属于工具系统,实际链路还经过 LLM Client、Agent 和权限模块。
继续查看职责后可以发现:工具类负责声明参数 Schema,Client 负责把模型输出解析成参数字典,Agent 负责执行前调度,具体工具负责检查文件状态、替换内容唯一性等语义约束。
因此,主模块仍然是工具系统,其他部分作为关联模块进入专题。
2. 追出当前问题需要的最小链路
最终得到的源码链是:
text
Tool.params_model
→ Tool.get_schema()
→ client.stream()
→ ToolCallComplete.arguments
→ Agent._execute_tool()
→ model_validate()
→ Tool.execute()
这条链已经足够回答参数从哪里来、在哪一层转换、在哪里完成结构校验,以及哪些约束必须由具体工具检查。
继续阅读后,可以把整个过程归纳为三层:
- Client 将模型返回的参数片段解析为 JSON 对象。
- Pydantic 根据工具声明的参数模型检查必填字段、类型和默认值。
- 具体工具在
execute()中检查文件是否存在、修改前是否读取、替换文本是否唯一等语义约束。
这里得到的结论不是根据通用 Agent 经验补出来的,而是分别锚定到了参数 Schema、Client 的 JSON 解析、Agent 的执行函数和具体工具实现。
3. 学完之后,不急着把专题标记为完成
这次学习已经弄清楚参数校验的主流程,但还留下了一个问题:是否需要统一开启严格类型检查,并禁止模型传入未声明字段?
当前源码只能证明系统使用了 Pydantic 的默认配置,不能直接证明"应该改成严格模式"。后者涉及模型兼容性和回归测试,需要进一步评估。
所以,稳定事实进入工具模块知识,未解决的问题保留在专题中,全局进度仍然把它标记为"学习中"。
真正的学习闭环不是强行得出最终结论,而是把已知、未知和下一步准确地区分开。
七、继续、复习和审计如何连接起来
有了分层记录之后,"继续学习"不再是一句模糊的提示词。
Agent 可以先读取全局进度,找到最近活跃专题,再查看当前问题和继续位置。如果存在多个同等重要的候选专题,再交给学习者选择,而不是擅自切换主线。
复习也不应该重新输出一遍原答案。
更有效的方式是根据已经验证的模块知识向学习者提问,等学习者回答后,再用源码锚点纠正理解。这时,知识文件不只是给 Agent 使用的上下文,也变成了生成复习问题的依据。
随着项目迭代,已有知识还需要接受审计。
审计会检查代码锚点是否仍然存在、主调用链是否已经变化、稳定知识是否与当前源码发生冲突。发现冲突后,先生成健康报告,再决定是否把旧知识标记为 stale。
于是,几种原本分散的学习动作被连接到了一起:

学习不再只是一次性的"问完就走",而是形成了学习、记录、继续、复习和校验之间的循环。
八、它与领域知识 Skill 有什么区别
这个项目学习 Skill 的设计,受到了"面向 Skills 编程"和领域知识工程思路的启发。
二者都强调按需加载知识、把结论映射到真实代码,并通过持续校验避免知识腐化。但它们服务的对象和最终目标并不完全相同。
| 类型 | 主要服务对象 | 核心目标 | 重点记录的内容 |
|---|---|---|---|
| 领域知识 Skill | 执行开发任务的 Code Agent | 让 Agent 正确理解业务并修改代码 | 业务规则、代码流程、变更约束 |
| 项目学习 Skill | 正在学习项目的人 | 让多次源码学习能够持续推进 | 学习问题、理解状态、模块知识、源码证据 |
领域知识 Skill 更关心"Agent 修改代码时必须知道什么",项目学习 Skill 更关心"学习者已经理解什么,下一步还需要弄清楚什么"。
一个是为 Agent 补充项目上下文,一个是让 Agent 帮助人建立项目认知。
二者真正相通的地方在于:无论知识最终给人还是给 Agent 使用,都必须能够回到当前源码进行验证。
九、项目学习 Skill 的边界
这套机制能够减少重复搜索、控制学习范围,并提高学习记录的可信度,但它不能自动保证所有理解都正确。
首先,源码锚点只能证明"系统现在怎么实现",不一定能解释"为什么当初这样设计"。如果涉及历史决策和业务背景,仍然需要查阅设计文档或向项目成员确认。
其次,学习记录不是越多越好。模块知识只应该保留跨会话仍然有价值的稳定事实,专题也只记录理解当前问题需要的内容。把全部源码解释和聊天原文都保存下来,只会让下一次加载重新陷入信息过载。
最后,Skill 只是约束 Agent 的工作方式。真正决定学习效果的,仍然是学习者能否提出具体问题、复述主链路,并通过运行项目、测试或断点验证自己的理解。
因此,这套方法更适合从一个真实问题开始:
- 选择当前确实想弄懂的机制。
- 定位职责所属模块。
- 只追一条最小源码链。
- 区分已验证结论和待验证推断。
- 留下明确的继续位置。
先跑通一个小闭环,再逐渐扩展到更多模块,比一开始为整个项目生成完整知识库更可靠。
十、总结
Code Agent 可以快速搜索和解释源码,但长期学习一个项目,需要解决的不只是"这次能不能看懂"。
如果多次学习之间没有连接,每次提问都要重新定位;如果没有控制源码范围,一次回答很容易塞入过多信息;如果不区分事实和推测,学习笔记还可能随着时间逐渐失真。
项目学习 Skill 给出的解决思路是:
- 用问题而不是目录驱动每次学习。
- 围绕"入口、核心处理、输出"追最小源码链。
- 用模块知识、问题专题和全局进度保存不同层次的信息。
- 用
verified、inferred、question和stale管理知识边界。 - 把学习、继续、复习和审计连接成长期闭环。
所以,真正值得沉淀的并不是一份越来越长的源码讲解,而是一套可以持续工作的学习方式:
让每次源码阅读都有明确问题,让每个稳定结论都有代码证据,让下一次学习能够接着上一次继续。
过去,我让 Agent 回答一个又一个彼此独立的问题。
现在,我更希望它陪我建立一套能够持续生长、也能不断自我校验的项目认知。
参考资料
- 阿里妈妈技术:《面向 Skills 编程:用领域知识工程驱动 Code Agent》
https://mp.weixin.qq.com/s/Z8KALAwVRTTXs94VolzMhg