别再让 AI Agent 重复踩坑:SkillLite 用 Repo Wiki 沉淀项目经验
AI Agent 工程中的核心问题不是单次失败,而是重复同样的错误。SkillLite 项目通过建立结构化经验库解决这一问题,其关键设计包括: 自动识别高价值失败信号(如重复工具失败、重规划) 用户确认后才将经验写入项目知识库 使用标准化模板记录关键四要素:发生了什么、根因、优化方案和检查清单 通过内容指纹校验保持知识新鲜度 区分原始资料(raw)和编译知识(wiki)两个存储层 这种设计既避免了
Agent 最大的问题不是失败,而是重复失败
做 AI Agent 工程时,我越来越明显地感觉到一个问题:一次工具调用失败并不可怕,可怕的是下一次还用同样的方式失败。
比如文件路径没确认就开始改代码,MCP 工具 schema 没读就直接调用,命令失败后又原样重试,计划已经走不通却没有及时 replan。这些错误并不是单点 bug,而是“经验没有沉淀下来”的结果。
所以我在 SkillLite 里补了一层项目经验库:不是把所有聊天记录存起来,而是把有复盘价值的内容整理成项目内 Markdown Wiki。它的目标很直接:让 Agent 的失败经验可以被人审查、被项目保存、被下一次查询到。
项目地址:SkillLite
这篇文章的核心问题
这篇文章讨论的是一个工程问题:
如何让 AI Agent 在项目里形成可维护的经验闭环?
SkillLite 的做法可以概括成六句话:
- 项目知识放在
.skilllite/wiki/。 - 原始资料先进入
raw/。 - 编译后的知识进入
wiki/。 - 查询前自动判断内容是否过期。
- 遇到 replan 或连续工具失败时,提示用户是否记录经验。
- 经验写入结构化 lesson,而不是完整聊天记录。
先看最终使用方式
用户不需要理解内部实现,也可以直接使用这组命令:
# 初始化项目 Wiki
skilllite wiki init --workspace .
# 把项目资料写入 raw,并默认生成可查询文章
skilllite wiki ingest docs/agent-debug-note.md --workspace .
# 查询项目经验
skilllite wiki query "tool failure retry strategy" --workspace .
# 查看 raw 和 compiled wiki 是否一致
skilllite wiki status --workspace .
# 校验 Wiki 结构和链接
skilllite wiki lint --workspace .
如果一次 chat 或桌面 Assistant 对话里出现了 replan,或者工具连续失败达到阈值,对话结束后会提示用户是否记录经验。用户确认后才会执行:
skilllite wiki record-lesson \
--workspace . \
--title "Conversation lesson: consecutive tool failures" \
--trigger consecutive_tool_failures \
--summary "连续工具失败后应先检查路径、schema 或命令输出" \
--body "## What Happened..."
这里最关键的不是命令数量,而是边界:自动提示,但不自动污染项目知识库。
流程图:从失败信号到项目经验
这个流程有一个设计原则:Agent 负责发现“值得记录的信号”,用户负责确认“是否进入项目知识库”。
为什么不直接存完整聊天记录?
完整聊天记录通常不是好知识。它里面有大量临时上下文、试错过程、无关输出,甚至可能包含不该进入项目仓库的信息。
对下一次 Agent 执行真正有帮助的,通常只有四件事:
| 需要沉淀的信息 | 作用 |
|---|---|
| 发生了什么 | 让后来者理解场景 |
| 根因是什么 | 避免再次误判 |
| 应该怎么优化 | 给 Agent 或开发者新的执行策略 |
| 下次检查什么 | 把经验变成 checklist |
所以 SkillLite 的 lesson 不保存聊天流水,而是保存经验模板:
## What Happened
这次发生了什么。
## Root Cause
确认后的根因是什么。
## Optimization
下次应该怎么调整执行方式。
## Next Time
- 先检查路径、命令输出、schema 或依赖。
- 不要重复同一个失败调用。
- 修复验证后更新这条 lesson。
这会让 Wiki 更像“项目经验手册”,而不是“聊天记录垃圾桶”。
代码看点一:什么时候提示记录经验?
SkillLite 并不会每轮对话都建议写 Wiki。触发条件被限制在几类高价值信号上:
pub const WIKI_CONSECUTIVE_TOOL_FAILURE_THRESHOLD: usize = 3;
pub enum WikiUpdateTrigger {
Replan,
ConsecutiveToolFailures,
RepeatedToolFailures,
}
判断逻辑也比较克制:
let trigger = if feedback.replans > 0 {
WikiUpdateTrigger::Replan
} else if feedback.max_consecutive_tool_failures >= WIKI_CONSECUTIVE_TOOL_FAILURE_THRESHOLD {
WikiUpdateTrigger::ConsecutiveToolFailures
} else if feedback.max_repeated_tool_failures >= WIKI_CONSECUTIVE_TOOL_FAILURE_THRESHOLD {
WikiUpdateTrigger::RepeatedToolFailures
} else {
return None;
};
普通成功对话不需要额外打扰用户。真正值得记录的是那些暴露出“执行策略问题”的对话。
代码看点二:建议 payload 里有什么?
当系统判断这轮对话值得复盘,会构造一个结构化建议:
pub struct WikiUpdateSuggestion {
pub trigger: WikiUpdateTrigger,
pub replan_count: usize,
pub failed_tool_count: usize,
pub failed_tools: Vec<String>,
pub error_summaries: Vec<String>,
pub proposed_title: String,
pub proposed_lesson: String,
}
这里没有直接写文件,而是生成一份“建议”。这份建议可以被 CLI chat 使用,也可以通过 RPC done 事件交给桌面 Assistant。
换句话说,Agent 层只输出结构化信号,真正的写入动作留给用户确认后的命令层。
代码看点三:record-lesson 如何避免写成散文?
用户传入的 body 可能很短,也可能格式不完整。为了保证 Wiki 里的 lesson 可用,命令层会补齐模板:
fn lesson_body_with_template(summary: &str, trigger: &str, body: &str) -> String {
let trimmed = body.trim();
if trimmed.contains("## What Happened")
&& trimmed.contains("## Root Cause")
&& trimmed.contains("## Optimization")
&& trimmed.contains("## Next Time")
{
return trimmed.to_string();
}
let what_happened = if trimmed.is_empty() {
summary.trim()
} else {
trimmed
};
format!(
"## What Happened\n\n{}\n\nTrigger: `{}`.\n\n\
## Root Cause\n\nDescribe the confirmed reason this run needed replanning or hit repeated tool failures.\n\n\
## Optimization\n\nDocument the improved approach that avoids repeating the same failed path.\n\n\
## Next Time\n\n- Check the relevant file path, command output, schema, or dependency first.\n- Change the approach before retrying the same tool call.\n- Keep this lesson updated after the successful fix is confirmed.\n",
what_happened,
trigger.trim()
)
}
这个函数的作用不是美化 Markdown,而是保证每条经验都能回答同一组问题。统一结构以后,后续查询、总结、人工 review 都更稳定。
Wiki 怎么保持新鲜?
只把资料写进 Markdown 还不够。项目资料会变,编译后的文章也会过期。
SkillLite 没有用文件时间戳判断 freshness,而是给 raw content 计算 fingerprint:
fn content_fingerprint(content: &str) -> String {
let mut hash = 0xcbf29ce484222325u64;
for byte in content.as_bytes() {
hash ^= u64::from(*byte);
hash = hash.wrapping_mul(0x100000001b3);
}
format!("fnv1a64:{hash:016x}")
}
编译文章时会把 fingerprint 写到 frontmatter:
sources: [raw/debug-note.md]
source_fingerprints: [raw/debug-note.md=fnv1a64:...]
后续 wiki status 或 wiki query 会重新计算 raw 的 fingerprint。如果对不上,就说明 compiled article 已经过期。
查询前自动刷新:不用 watcher 也能动态维护
很多知识库一提“动态更新”,就会想到后台 watcher。但 watcher 会带来额外复杂度:进程管理、跨平台差异、误触发、资源占用、写入时机不可控。
SkillLite 采用了更简单的策略:查询前检查。
if !no_compile {
let freshness = wiki_freshness(&wiki)?;
if freshness.needs_refresh() {
let compiled = compile_raw_sources(&wiki)?;
rebuild_indexes(&wiki)?;
append_log(
&wiki,
"auto-compile",
&format!("Refreshed {} raw source(s) before query", compiled),
)?;
}
}
这样做的好处是:
- 不需要常驻进程。
- 不会在用户无感知时不断写文件。
- 每次查询都能尽量拿到最新结果。
- 需要保留旧状态时,可以用
--no-compile跳过刷新。
为什么主存储选 Markdown,而不是 SQLite?
SQLite 很适合做索引,但这次我不想让它成为 Repo Wiki 的事实来源。
项目经验库首先要服务团队协作,而 Markdown 在这方面更自然:
| 维度 | Markdown | SQLite |
|---|---|---|
| 人能不能直接读 | 可以 | 不方便 |
| Code Review 是否友好 | 友好 | 不直观 |
| Git 冲突是否可处理 | 可手动处理 | 通常更麻烦 |
| LLM 是否容易读取 | 容易 | 需要查询层 |
| 适合作为什么 | 事实来源 | 派生索引或缓存 |
所以当前设计是:Markdown 是主存储,未来如果需要向量召回或复杂检索,可以在 Markdown 之上再生成索引。
CSDN 发布建议
这篇文章可以直接用下面这个标题:
别再让 AI Agent 重复踩坑:SkillLite 用 Repo Wiki 沉淀项目经验
如果想更偏搜索,可以用:
AI Agent 项目经验库实践:SkillLite 的 LLM Wiki 自动维护方案
如果想更偏工程复盘,可以用:
从工具失败到经验沉淀:SkillLite 的 Repo Wiki 设计复盘
摘要建议控制在 120 字左右:
本文介绍 SkillLite 如何用 Markdown-only Repo Wiki 沉淀 AI Agent 的项目经验:通过 raw/wiki 分层、source fingerprint、查询前自动刷新,以及 replan/连续工具失败后的用户确认式 lesson 记录,让 Agent 的失败经验变成可审查、可复用的项目知识。
FAQ
这套机制是自动写 Wiki 吗?
不是静默自动写。ingest 和 query 会触发自动编译或刷新;对话失败经验只会生成建议,用户确认后才写入。
为什么连续工具失败阈值是 3?
一次失败可能是偶发,两次失败可能是参数问题,连续三次通常说明策略或前置检查有问题,值得提示复盘。
record-lesson 会保存完整对话吗?
不会。它保存结构化经验,包括发生了什么、根因、优化方式和下次检查项。
.skilllite/wiki/ 可以提交到 Git 吗?
它是项目级 Markdown 知识库,具备可提交和可审查的条件。是否提交取决于团队策略以及内容是否包含敏感信息。
这和 memory 有什么区别?
memory 更偏用户级、跨项目、私有长期记忆;Repo Wiki 更偏项目级、可读、可审查、可协作的知识。
总结
SkillLite 这次做的不是“再加一个文档目录”,而是给 AI Agent 增加一个项目经验闭环:
- 项目资料进入
.skilllite/wiki/raw/。 - 编译后生成可查询的 Wiki 文章。
- fingerprint 判断知识是否过期。
- query 前自动刷新 stale 内容。
- replan 和连续工具失败触发经验记录建议。
- 用户确认后写入结构化 lesson。
对 Agent 系统来说,真正有价值的不是把所有上下文都保存下来,而是把失败中提炼出的经验留在项目里。这样下一次执行时,Agent 不只是“重新尝试”,而是能带着项目已经验证过的经验继续工作。
更多推荐




所有评论(0)