面向Skills学习:用领域知识工程驱动 Code Agent 学习

你好,我是程序员无隅

🌈 这是我的个人主页: 无隅的主页

🌟 "技术永无止境,希望我的内容能帮到你"


最近我一直在学习一个 Coding Agent 项目。

最开始,我的学习方式很直接:遇到看不懂的模块,就让 Agent 搜索源码、梳理调用链,然后把结果讲给我。

这种方式在单次对话里很好用,但只要学习时间被拉长,问题很快就出现了。

今天刚弄清楚工具参数如何校验,过几天再问相关问题,Agent 又要重新搜索入口;上次还没有理解的地方,没有明确的继续位置;某些结论只是根据局部代码推测出来的,却可能在后续对话中被当成项目事实。

我逐渐发现:长期学习一个项目,真正困难的不是让 Agent 读懂一次源码,而是让多次学习之间能够连接起来。

为了解决这个问题,我写了一个项目学习 Skill。它不负责替我生成一份庞大的项目说明书,而是约束 Agent 如何定位问题、阅读源码、组织讲解,并把经过验证的知识沉淀下来。

本文的核心观点是:项目学习 Skill 不是一个自动总结器,而是一套学习工作流。问题驱动决定本次学什么,最小源码链控制阅读范围,分层记录保存学习状态,知识边界保证结论可信。


一、普通 AI 问答为什么不适合长期学习项目

在一次独立对话中,Agent 的源码分析能力通常已经足够强。

我们可以问它某个函数的作用,也可以让它从入口追到下游,甚至可以让它对比两个模块的设计差异。真正的问题出现在第二次、第三次以及更多次学习之后。

1. 每次对话都容易重新开始

假设我第一次学习了工具注册,第二次学习参数校验,第三次想继续研究权限判断。

如果没有统一的学习记录,Agent 并不知道哪些内容已经理解、哪些只是看过、哪些问题上次还没有解决。为了保证回答准确,它只能重新搜索相关文件,再重建一遍上下文。

于是,项目学习很容易退化成下面的循环:

  1. 提出一个源码问题。
  2. Agent 在项目中重新搜索。
  3. Agent 给出一份当前对话中的解释。
  4. 对话结束,学习状态没有被结构化保存。
  5. 下次遇到相邻问题,再从定位模块开始。

单次回答可能是正确的,但多次回答没有形成可以复用的学习成果。

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()

这条链已经足够回答参数从哪里来、在哪一层转换、在哪里完成结构校验,以及哪些约束必须由具体工具检查。

继续阅读后,可以把整个过程归纳为三层:

  1. Client 将模型返回的参数片段解析为 JSON 对象。
  2. Pydantic 根据工具声明的参数模型检查必填字段、类型和默认值。
  3. 具体工具在 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 的工作方式。真正决定学习效果的,仍然是学习者能否提出具体问题、复述主链路,并通过运行项目、测试或断点验证自己的理解。

因此,这套方法更适合从一个真实问题开始:

  1. 选择当前确实想弄懂的机制。
  2. 定位职责所属模块。
  3. 只追一条最小源码链。
  4. 区分已验证结论和待验证推断。
  5. 留下明确的继续位置。

先跑通一个小闭环,再逐渐扩展到更多模块,比一开始为整个项目生成完整知识库更可靠。


十、总结

Code Agent 可以快速搜索和解释源码,但长期学习一个项目,需要解决的不只是"这次能不能看懂"。

如果多次学习之间没有连接,每次提问都要重新定位;如果没有控制源码范围,一次回答很容易塞入过多信息;如果不区分事实和推测,学习笔记还可能随着时间逐渐失真。

项目学习 Skill 给出的解决思路是:

  1. 用问题而不是目录驱动每次学习。
  2. 围绕"入口、核心处理、输出"追最小源码链。
  3. 用模块知识、问题专题和全局进度保存不同层次的信息。
  4. verifiedinferredquestionstale 管理知识边界。
  5. 把学习、继续、复习和审计连接成长期闭环。

所以,真正值得沉淀的并不是一份越来越长的源码讲解,而是一套可以持续工作的学习方式:

让每次源码阅读都有明确问题,让每个稳定结论都有代码证据,让下一次学习能够接着上一次继续。

过去,我让 Agent 回答一个又一个彼此独立的问题。

现在,我更希望它陪我建立一套能够持续生长、也能不断自我校验的项目认知。


参考资料

相关推荐
_oP_i4 小时前
ai制作系统操作手册
ai
geinvse_seg8 小时前
飞算JavaAI:把企业采购协同需求拆成一套可运行的慧采平台
java·ai·飞算
不爱记笔记8 小时前
音视频内容如何纳入Obsidian知识库?分享一套完整的输入层解决方案
人工智能·ai·chatgpt·音视频·知识库·知识管理·obsidian
笨蛋©8 小时前
2026制造业质量管理实战:从工程图纸识别到检验计划自动化的进阶指南
ai·数字化·质量管理·制造业·图纸识别
俊哥V10 小时前
每日 AI 研究简报 · 2026-07-16
人工智能·ai
曦尧10 小时前
OpenMAIC:清华团队用多智能体重新发明「网课」,从 MOOC 到 MAIC 的范式跃迁
ai·自动化
程序猿编码12 小时前
没有AI框架,没有GPU,一个C语言文件跑通大模型
c语言·开发语言·人工智能·深度学习·ai·大模型
ks_szyxjs12 小时前
K3又是什么东东?
ai·月之暗面·kimi k3·moonshot
奇牙coding13 小时前
gpt-5.6-luna 调用报 400 bad_request 怎么办?同样的 messages 在 gpt-5.5 没问题——两处校验差异和修复写法
java·windows·gpt·ai