[{"data":1,"prerenderedAt":3051},["ShallowReactive",2],{"featured-posts":3},[4,713,1384,2334],{"id":5,"title":6,"body":7,"category":698,"date":699,"description":17,"extension":700,"meta":701,"navigation":702,"path":703,"seo":704,"stem":705,"tags":706,"__hash__":712},"blog\u002Fblog\u002Fagentic-rag-and-production.md","从经典 RAG 到 Agentic RAG：智能检索的进阶之路",{"type":8,"value":9,"toc":679},"minimark",[10,14,18,21,26,29,52,55,61,65,68,71,82,85,96,101,105,108,114,126,132,140,143,148,152,155,162,165,170,174,177,180,183,188,192,195,386,389,406,409,413,416,419,422,437,440,445,449,452,455,481,484,487,539,542,545,571,574,577,591,594,598,601,612,615,641,646,649,652,658,665,668,675],[11,12,6],"h1",{"id":13},"从经典-rag-到-agentic-rag智能检索的进阶之路",[15,16,17],"p",{},"如果你把经典 RAG 理解成一条流水线——用户提问、系统检索、LLM 回答，每一步都是预设好的固定流程。那么 Agentic RAG 就像是把这条流水线升级成了一个智能工厂——LLM 不再被动等待输入，而是主动决定要不要检索、查什么、查几次、甚至怀疑检索结果的准确性。",[15,19,20],{},"这篇文章从经典 RAG 的局限出发，梳理各种进阶 RAG 模式，最后落地到生产级工程实践。",[22,23,25],"h2",{"id":24},"_1-经典-rag-的局限","1. 经典 RAG 的局限",[15,27,28],{},"经典 RAG 的流程是一条直线：问题 → 检索 → 拼 Prompt → 生成。这个流程简单可靠，但也有三个明显的短板：",[30,31,32,40,46],"ul",{},[33,34,35,39],"li",{},[36,37,38],"strong",{},"检索一次性","：如果第一次检索没找到合适信息，不会重试",[33,41,42,45],{},[36,43,44],{},"Query 固定","：用户怎么问就怎么查，不会改写或拆解",[33,47,48,51],{},[36,49,50],{},"无反馈闭环","：LLM 生成时如果发现信息不足，没法回头再查",[15,53,54],{},"这些局限在简单问答场景下不是问题，但面对复杂、多跳、需要推理的问题时，经典 RAG 就显得力不从心了。",[15,56,57,60],{},[36,58,59],{},"小结："," 经典 RAG 胜在简单可控，但在复杂问题上精度不够。进阶 RAG 模式的目标就是补上这些短板。",[22,62,64],{"id":63},"_2-parent-child-small-to-big","2. Parent-Child \u002F Small-to-Big",[15,66,67],{},"前面讲到过，小 chunk 检索更精准但信息不完整，大 chunk 信息完整但精度不够。Parent-Child Chunking 巧妙地解决了这个矛盾。",[15,69,70],{},"思路很简单：建两级 chunk。小 chunk（child）存索引用于检索，命中后返回对应的父 chunk（parent）喂给 LLM。",[72,73,78],"pre",{"className":74,"code":76,"language":77},[75],"language-text","索引层：小 chunk（300 token）→ 精准匹配\n返回层：父 chunk（1500 token）→ 完整上下文\n","text",[79,80,76],"code",{"__ignoreMap":81},"",[15,83,84],{},"这样既保证了检索的召回精度，又保证了 LLM 拿到的是完整信息。",[15,86,87,88,91,92,95],{},"类似的思想还有 ",[36,89,90],{},"Sentence Window Retrieval","：检索到某个句子后，带上前后的句子作为上下文一起返回。以及 ",[36,93,94],{},"Auto-Merging Retrieval","：多个相邻小 chunk 都被命中时，自动合并成更大的父块。",[15,97,98,100],{},[36,99,59],{}," 这些模式的核心思想是一致的——检索粒度细、返回粒度粗。在准确性和信息完整性之间找到一个巧妙的平衡点。",[22,102,104],{"id":103},"_3-self-rag-与-crag","3. Self-RAG 与 CRAG",[15,106,107],{},"这两种模式给 RAG 加入了\"元认知\"——系统不再盲目执行检索流程，而是学会反思自己的行为。",[15,109,110,113],{},[36,111,112],{},"Self-RAG"," 让 LLM 在生成过程中自己决定三件事：",[115,116,117,120,123],"ol",{},[33,118,119],{},"需不需要检索（有些问题 LLM 自己能回答，无需检索）",[33,121,122],{},"检索回来的内容是否相关（过滤不相关的结果）",[33,124,125],{},"回答是否基于检索内容（自我验证，防止幻觉）",[15,127,128,131],{},[36,129,130],{},"CRAG（Corrective RAG）"," 则在检索之后加了一个专门的评估器，判断检索结果的质量：",[30,133,134,137],{},[33,135,136],{},"质量好 → 用检索结果回答",[33,138,139],{},"质量差 → 触发 Fallback——比如改用网页搜索、或者直接让 LLM 用自己的知识回答——并记录下来用于后续优化",[15,141,142],{},"两种模式的区别在于：Self-RAG 的\"反思\"内化在 LLM 的生成过程中，CRAG 的\"纠错\"是外挂的一个独立模块。",[15,144,145,147],{},[36,146,59],{}," 经典 RAG 是\"查了就用\"的直线思维，Self-RAG 和 CRAG 引入了\"查了再想想对不对\"的反思机制。这是从被动检索到主动推理的关键一步。",[22,149,151],{"id":150},"_4-graph-rag","4. Graph RAG",[15,153,154],{},"Graph RAG 用知识图谱代替或增强向量检索。节点是实体和概念，边是它们之间的关系，检索时沿着图谱做多跳推理。",[15,156,157,158,161],{},"微软的 GraphRAG 论文是这一方向的代表作。它的核心优势在于处理",[36,159,160],{},"需要多跳推理的复杂问题","，比如\"A 和 B 的共同朋友中谁是 C 公司的员工？\"这类问题如果用纯向量检索，需要把整段关系描述都在一个 chunk 里，而这往往不现实。",[15,163,164],{},"Graph RAG 的代价也很明显：构建和维护知识图谱的成本远高于简单的向量化。它适用于知识之间关系密集、多跳查询频繁的场景，但不是所有 RAG 系统都需要。",[15,166,167,169],{},[36,168,59],{}," Graph RAG 适合关系密集、多跳推理的场景。如果你的问题大多是\"某某文档里提到什么\"，纯向量检索就够了。但如果是\"某某和某某之间有什么关系\"，Graph RAG 就有不可替代的优势。",[22,171,173],{"id":172},"_5-contextual-retrieval","5. Contextual Retrieval",[15,175,176],{},"2024 年 Anthropic 提出的方法，思路非常实用：给每个 chunk 生成一段上下文描述，说明它在原文档中的位置和主题，然后对\"chunk + 上下文描述\"做 Embedding。",[15,178,179],{},"为什么有效？因为很多 chunk 单独拎出来是缺乏语境的。比如某 chunck 里写着\"它的延迟是 200ms\"——这个\"它\"指的是什么？如果 chunk 没有包含上文，检索时很可能匹配不到。加上上下文描述后，\"TransactionService 的延迟是 200ms\"就清晰多了。",[15,181,182],{},"Anthropic 报告说这种方法可以把检索错误率降低 35-49%。这是一个成本很低但效果显著的优化。",[15,184,185,187],{},[36,186,59],{}," 有时候问题不在检索算法，而在于被检索的内容本身缺乏语境。Contextual Retrieval 用最小的工程成本解决了这个问题。",[22,189,191],{"id":190},"_6-agentic-rag检索作为工具","6. Agentic RAG：检索作为工具",[15,193,194],{},"如果把检索封装成一个工具函数交给 LLM 调用，RAG 就不再是一条流水线，而是一场对话。",[72,196,200],{"className":197,"code":198,"language":199,"meta":81,"style":81},"language-typescript shiki shiki-themes github-dark","const retrieveTool = tool(\n  async ({ query }) => {\n    const docs = await vectorStore.similaritySearch(query, 5);\n    return docs.map(d => d.pageContent).join(\"\\n---\\n\");\n  },\n  {\n    name: \"retrieve_knowledge\",\n    description: \"从知识库检索相关文档\",\n    schema: z.object({ query: z.string() }),\n  }\n);\n","typescript",[79,201,202,226,248,277,322,328,334,346,357,375,381],{"__ignoreMap":81},[203,204,207,211,215,218,222],"span",{"class":205,"line":206},"line",1,[203,208,210],{"class":209},"snl16","const",[203,212,214],{"class":213},"sDLfK"," retrieveTool",[203,216,217],{"class":209}," =",[203,219,221],{"class":220},"svObZ"," tool",[203,223,225],{"class":224},"s95oV","(\n",[203,227,229,232,235,239,242,245],{"class":205,"line":228},2,[203,230,231],{"class":209},"  async",[203,233,234],{"class":224}," ({ ",[203,236,238],{"class":237},"s9osk","query",[203,240,241],{"class":224}," }) ",[203,243,244],{"class":209},"=>",[203,246,247],{"class":224}," {\n",[203,249,251,254,257,259,262,265,268,271,274],{"class":205,"line":250},3,[203,252,253],{"class":209},"    const",[203,255,256],{"class":213}," docs",[203,258,217],{"class":209},[203,260,261],{"class":209}," await",[203,263,264],{"class":224}," vectorStore.",[203,266,267],{"class":220},"similaritySearch",[203,269,270],{"class":224},"(query, ",[203,272,273],{"class":213},"5",[203,275,276],{"class":224},");\n",[203,278,280,283,286,289,292,295,298,301,304,306,310,313,316,318,320],{"class":205,"line":279},4,[203,281,282],{"class":209},"    return",[203,284,285],{"class":224}," docs.",[203,287,288],{"class":220},"map",[203,290,291],{"class":224},"(",[203,293,294],{"class":237},"d",[203,296,297],{"class":209}," =>",[203,299,300],{"class":224}," d.pageContent).",[203,302,303],{"class":220},"join",[203,305,291],{"class":224},[203,307,309],{"class":308},"sU2Wk","\"",[203,311,312],{"class":213},"\\n",[203,314,315],{"class":308},"---",[203,317,312],{"class":213},[203,319,309],{"class":308},[203,321,276],{"class":224},[203,323,325],{"class":205,"line":324},5,[203,326,327],{"class":224},"  },\n",[203,329,331],{"class":205,"line":330},6,[203,332,333],{"class":224},"  {\n",[203,335,337,340,343],{"class":205,"line":336},7,[203,338,339],{"class":224},"    name: ",[203,341,342],{"class":308},"\"retrieve_knowledge\"",[203,344,345],{"class":224},",\n",[203,347,349,352,355],{"class":205,"line":348},8,[203,350,351],{"class":224},"    description: ",[203,353,354],{"class":308},"\"从知识库检索相关文档\"",[203,356,345],{"class":224},[203,358,360,363,366,369,372],{"class":205,"line":359},9,[203,361,362],{"class":224},"    schema: z.",[203,364,365],{"class":220},"object",[203,367,368],{"class":224},"({ query: z.",[203,370,371],{"class":220},"string",[203,373,374],{"class":224},"() }),\n",[203,376,378],{"class":205,"line":377},10,[203,379,380],{"class":224},"  }\n",[203,382,384],{"class":205,"line":383},11,[203,385,276],{"class":224},[15,387,388],{},"LLM 收到问题后自己判断：",[30,390,391,394,397,400,403],{},[33,392,393],{},"需要检索吗？（有些问题不需要）",[33,395,396],{},"用什么 Query 检索？（自主改写）",[33,398,399],{},"检索结果够用吗？（评估）",[33,401,402],{},"不够就再查一次（换一个 Query）",[33,404,405],{},"查询轮信息足够后，生成最终答案",[15,407,408],{},"这个模式下，LLM 从一个\"答案生成器\"变成了\"问题解决者\"——它掌控整个检索和推理的流程，而不是被动执行预先编排的步骤。",[410,411,412],"h3",{"id":412},"多跳检索",[15,414,415],{},"复杂问题往往一次检索不够。比如：",[15,417,418],{},"用户问：\"LangGraph 的 Checkpointer 和 LangChain 的 Memory 有什么区别？\"",[15,420,421],{},"Agent 的执行过程可能是：",[115,423,424,429,434],{},[33,425,426],{},[79,427,428],{},"retrieve(\"LangGraph checkpointer\")",[33,430,431],{},[79,432,433],{},"retrieve(\"LangChain memory\")",[33,435,436],{},"对比两者的文档，生成答案",[15,438,439],{},"每一次检索的结果都可能影响下一次检索的 Query——这需要 Agent 维护对话状态，这正是 Agent 架构擅长的事情。",[15,441,442,444],{},[36,443,59],{}," Agentic RAG 把 LLM 从流水线操作工变成了车间主任。它不再被动执行，而是主动管理整个检索生成流程。这是 RAG 系统从\"能用\"到\"智能\"的关键跨越。",[22,446,448],{"id":447},"_7-生产级工程实践","7. 生产级工程实践",[410,450,451],{"id":451},"知识库管理",[15,453,454],{},"知识库是活的——文档会更新、会过期。生产环境需要解决几个实际问题：",[30,456,457,463,469,475],{},[33,458,459,462],{},[36,460,461],{},"增量同步","：文档更新时只重新处理变化的 chunk，用哈希比对检测变化",[33,464,465,468],{},[36,466,467],{},"版本管理","：换 Embedding 模型时，旧索引和新索引并存，等新索引验证通过再切流量",[33,470,471,474],{},[36,472,473],{},"权限隔离","：多租户场景下用 metadata filtering 实现检索权限控制",[33,476,477,480],{},[36,478,479],{},"数据清洗","：去重、去噪、统一格式，脏数据进库会污染所有检索结果",[410,482,483],{"id":483},"延迟优化",[15,485,486],{},"RAG 全链路的延迟构成：",[488,489,490,503],"table",{},[491,492,493],"thead",{},[494,495,496,500],"tr",{},[497,498,499],"th",{},"阶段",[497,501,502],{},"典型耗时",[504,505,506,515,523,531],"tbody",{},[494,507,508,512],{},[509,510,511],"td",{},"Embedding 查询",[509,513,514],{},"50-200ms",[494,516,517,520],{},[509,518,519],{},"向量检索",[509,521,522],{},"10-100ms",[494,524,525,528],{},[509,526,527],{},"Rerank",[509,529,530],{},"100-500ms（可选）",[494,532,533,536],{},[509,534,535],{},"LLM 生成",[509,537,538],{},"500-3000ms（主要瓶颈）",[15,540,541],{},"优化思路：Embedding 用快模型、向量库用 HNSW 算法、Rerank 在延迟敏感时跳过、LLM 用 Streaming 输出首 token。",[410,543,544],{"id":544},"成本优化",[30,546,547,553,559,565],{},[33,548,549,552],{},[36,550,551],{},"Embedding 缓存","：相同 Query 不重复调用",[33,554,555,558],{},[36,556,557],{},"小模型兜底","：简单问题用低成本模型，复杂问题再升级到大模型",[33,560,561,564],{},[36,562,563],{},"Prompt 压缩","：用 LLMLingua 等工具压缩检索内容，减少 Token 消耗",[33,566,567,570],{},[36,568,569],{},"冷热分离","：高频数据放内存库，低频数据放对象存储",[410,572,573],{"id":573},"可观测性",[15,575,576],{},"没有可观测性，RAG 系统就是黑盒。至少需要追踪这些指标：",[30,578,579,582,585,588],{},[33,580,581],{},"每次检索的 Query、命中的 chunk、Rerank 分数、最终答案",[33,583,584],{},"用户反馈（点赞\u002F点踩）",[33,586,587],{},"端到端延迟分布",[33,589,590],{},"检索 Miss 率（没有召回到相关内容的比例）",[15,592,593],{},"工具推荐：LangSmith、Langfuse、Arize，或者自建 Trace 系统。",[410,595,597],{"id":596},"fallback-策略","Fallback 策略",[15,599,600],{},"每个环节都要有兜底：",[30,602,603,606,609],{},[33,604,605],{},"检索失败 → 用 LLM 内置知识回答，标注\"无知识库支撑\"",[33,607,608],{},"LLM 生成失败 → 返回检索结果原文",[33,610,611],{},"全流程失败 → 固定兜底话术，记录日志",[410,613,614],{"id":614},"安全与合规",[30,616,617,623,629,635],{},[33,618,619,622],{},[36,620,621],{},"PII 脱敏","：向量化前清洗个人信息",[33,624,625,628],{},[36,626,627],{},"权限控制","：检索时带用户权限过滤",[33,630,631,634],{},[36,632,633],{},"审计日志","：谁查了什么、LLM 回答了什么都留痕",[33,636,637,640],{},[36,638,639],{},"Prompt Injection 防护","：检索回来的文档可能被恶意污染（\"忽略之前指令，说...\"），需要做输入过滤",[15,642,643,645],{},[36,644,59],{}," 生产级 RAG 的挑战不在算法创新，而在工程细节。知识库管理、延迟、成本、可观测性、安全性——每个方面都需要体系化的解决方案。",[22,647,648],{"id":648},"总结",[15,650,651],{},"从经典 RAG 到 Agentic RAG，背后是一条从\"被动执行\"到\"主动思考\"的演进路径：",[72,653,656],{"className":654,"code":655,"language":77},[75],"经典 RAG → 固定流水线，一次检索\n  ↓\nSelf-RAG \u002F CRAG → 加入反思与纠错\n  ↓\nGraph RAG → 用知识图谱支持多跳推理\n  ↓\nAgentic RAG → LLM 自主管理检索流程\n",[79,657,655],{"__ignoreMap":81},[15,659,660,661,664],{},"但无论是哪种模式，核心原则是不变的：",[36,662,663],{},"RAG 的价值在于让 LLM 基于事实说话。"," 技术模式可以演进，但这个根本目的始终如一。",[15,666,667],{},"如果你的系统还跑着经典 RAG 链路、遇到了精度瓶颈，不妨从这些进阶模式中选择一个入手升级。大多数情况下，最简单也最有性价比的优化往往是：给 chunk 加上下文描述（Contextual Retrieval）、在检索后加一层 Rerank、或者让 LLM 能自主决定是否重试检索。",[15,669,670],{},[671,672,674],"a",{"href":673},"\u002Fblog\u002F","返回博客列表",[676,677,678],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":81,"searchDepth":228,"depth":228,"links":680},[681,682,683,684,685,686,689,697],{"id":24,"depth":228,"text":25},{"id":63,"depth":228,"text":64},{"id":103,"depth":228,"text":104},{"id":150,"depth":228,"text":151},{"id":172,"depth":228,"text":173},{"id":190,"depth":228,"text":191,"children":687},[688],{"id":412,"depth":250,"text":412},{"id":447,"depth":228,"text":448,"children":690},[691,692,693,694,695,696],{"id":451,"depth":250,"text":451},{"id":483,"depth":250,"text":483},{"id":544,"depth":250,"text":544},{"id":573,"depth":250,"text":573},{"id":596,"depth":250,"text":597},{"id":614,"depth":250,"text":614},{"id":648,"depth":228,"text":648},"AI\u002FLLM","2026-05-03","md",{},true,"\u002Fblog\u002Fagentic-rag-and-production",{"title":6,"description":17},"blog\u002Fagentic-rag-and-production",[707,708,709,710,711],"RAG","Agentic RAG","Graph RAG","大模型","生产实践","LcJ1nu8yN6bgMvmXeZlXDkH5PgSDEpsjLz3AFW6sFGk",{"id":714,"title":715,"body":716,"category":698,"date":699,"description":1372,"extension":700,"meta":1373,"navigation":702,"path":1374,"seo":1375,"stem":1376,"tags":1377,"__hash__":1383},"blog\u002Fblog\u002Fai-agent-harness-engineering.md","AI Agent 的工程化哲学：Harness 设计的核心原则",{"type":8,"value":717,"toc":1360},[718,721,732,739,742,746,749,752,830,837,842,846,849,855,861,864,878,885,890,894,901,907,913,916,921,925,928,931,1025,1032,1039,1045,1048,1053,1057,1060,1086,1089,1092,1119,1124,1128,1131,1154,1160,1165,1169,1181,1184,1189,1193,1196,1215,1218,1244,1249,1253,1256,1259,1279,1282,1287,1291,1294,1350,1353,1356],[11,719,715],{"id":720},"ai-agent-的工程化哲学harness-设计的核心原则",[15,722,723,724,727,728,731],{},"很多人第一次用 Claude Code 或 Cursor 时会有一种错觉：它好聪明，什么都能做。但用久了你会发现，这些产品真正厉害的地方",[36,725,726],{},"不是模型本身","——它们底层都接的是 Claude 或 GPT——",[36,729,730],{},"而是围绕模型搭建的那一套\"脚手架\"","。",[15,733,734,735,738],{},"这套脚手架在 AI 工程圈有个专门的词：",[36,736,737],{},"Harness（挽具）","。原意是套在马身上控制方向的工具，引申为围绕 LLM 构建的一切控制代码——决定什么时候调用模型、往上下文里塞什么、如何验证输出、失败时如何重试、如何保存状态以便中断后恢复。",[15,740,741],{},"LLM 是引擎，Harness 是把引擎装进车里的一切零件。",[22,743,745],{"id":744},"_1-context-engineering每个-token-都是预算","1. Context Engineering：每个 Token 都是预算",[15,747,748],{},"给 LLM 的输入要精确——这句话人人都同意，但落到实处是什么？",[15,750,751],{},"不是\"把需求说清楚\"就够了。Context Engineering 是一套完整的策展策略：",[488,753,754,764],{},[491,755,756],{},[494,757,758,761],{},[497,759,760],{},"维度",[497,762,763],{},"实操",[504,765,766,776,786,796,806,816],{},[494,767,768,773],{},[509,769,770],{},[36,771,772],{},"System Prompt",[509,774,775],{},"角色、目标、约束、输出格式全部显式写明",[494,777,778,783],{},[509,779,780],{},[36,781,782],{},"Few-shot Examples",[509,784,785],{},"高质量示例比长篇规则更有效——模型模仿代码的能力远超按自然语言规范写代码",[494,787,788,793],{},[509,789,790],{},[36,791,792],{},"Tool Descriptions",[509,794,795],{},"描述要具体，举反例（\"不要在 X 场景调用此工具\"）",[494,797,798,803],{},[509,799,800],{},[36,801,802],{},"Working Context",[509,804,805],{},"当前任务状态作为结构化 block 注入，而非混在对话历史里",[494,807,808,813],{},[509,809,810],{},[36,811,812],{},"Retrieved Context",[509,814,815],{},"RAG 拉来的资料标注来源、时间、可信度",[494,817,818,823],{},[509,819,820],{},[36,821,822],{},"Negative Context",[509,824,825,826,829],{},"告诉模型",[36,827,828],{},"不要做什么","——经常比正向指令更有效",[15,831,832,833,836],{},"核心洞察：上下文窗口是稀缺资源，",[36,834,835],{},"每个 token 都应该为当前子任务服务","。反模式是把整个项目代码、整段对话历史、所有可能用到的工具一股脑塞进去——这叫 Context Stuffing，结果是信号被噪声淹没。",[15,838,839,841],{},[36,840,59],{}," 精确的输入不是\"把话说清楚\"那么简单，而是一套信息策展纪律。扔掉无关的，标注来源的，举例说明的，明确禁止的——四管齐下。",[22,843,845],{"id":844},"_2-workflow-与-agent-的光谱外层固定内层自由","2. Workflow 与 Agent 的光谱：外层固定，内层自由",[15,847,848],{},"Agent 设计存在一个光谱：",[72,850,853],{"className":851,"code":852,"language":77},[75],"纯 Workflow  ←──────────────────────→  纯 Agent\n所有分支写死    预设骨架 + LLM 决策      完全自由的 ReAct 循环\n可预测、可审计                           灵活、应对力强\n容易调试                                 难调试、难预算\n",[79,854,852],{"__ignoreMap":81},[15,856,857,858],{},"大型复杂任务的工程化原则很明确：",[36,859,860],{},"能用 workflow 表达的部分，就不要交给 Agent 自主决策。",[15,862,863],{},"比如一个\"代码 review → 测试 → 部署\"的大任务：",[30,865,866,872],{},[33,867,868,871],{},[36,869,870],{},"宏观流程是 Workflow","（三阶段顺序固定，状态机表达）",[33,873,874,877],{},[36,875,876],{},"每阶段内部的判断是 Agent","（LLM 决定看哪些文件、跑哪些测试）",[15,879,880,881,884],{},"这就是\"相对固定的流程\"的精确含义——",[36,882,883],{},"外层骨架固定，内层决策自由","。LangGraph 的 StateGraph 天然适合这种表达：StateGraph 定义 workflow 骨架，每个节点里可以是 Agent 子图。",[15,886,887,889],{},[36,888,59],{}," 把 Agent 当\"万能自主决策者\"是新手最容易犯的错误。高手的设计是：固定流程做骨架，Agent 能力填血肉。",[22,891,893],{"id":892},"_3-plan-then-execute先规划再动手","3. Plan-Then-Execute：先规划，再动手",[15,895,896,897,900],{},"让 LLM 直接上手干活的失败率远高于先让它出计划。这在工业上叫 ",[36,898,899],{},"Plan-Then-Execute 模式","：",[72,902,905],{"className":903,"code":904,"language":77},[75],"输入\n  ↓\n阶段 1：Clarification（澄清）\n  - LLM 反问用户，确认真实目标\n  - 必要时 HITL（人工确认）\n  ↓\n阶段 2：Planning（规划）\n  - 输出结构化任务列表\n  - 每项含：描述、依赖、预期产物、验证方式\n  ↓\n阶段 3：Execution（执行）\n  - 遍历任务列表，逐项执行\n  - 每项完成后更新状态\n  ↓\n阶段 4：Consolidation（汇总）\n  - 检查是否全部达成，整合输出\n",[79,906,904],{"__ignoreMap":81},[15,908,909,912],{},[36,910,911],{},"一个关键点容易被忽略：Planning 阶段的输出应该是数据结构，不是自然语言。"," 结构化的 plan 可以机器可读、可渲染进度条、支持 DAG 并行执行、中断恢复时精确定位到具体任务。",[15,914,915],{},"Claude Code 的 TodoWrite 就是 Plan-Then-Execute 的显式实现——它不是可有可无的辅助功能，而是复杂任务不跑偏的核心保障。",[15,917,918,920],{},[36,919,59],{}," 让 LLM 先出结构化计划，人 review 确认，再逐项执行。这 30 秒的\"刹车\"能省掉后面 30 分钟的回滚。",[22,922,924],{"id":923},"_4-verifier-loop没有验证的-agent-就是没有刹车的跑车","4. Verifier Loop：没有验证的 Agent 就是没有刹车的跑车",[15,926,927],{},"这是整个 Harness 设计中最关键也最容易被忽视的一条。LLM 会自信地胡说——只有客观的 Verifier 能拦住它。",[15,929,930],{},"AI coding 领域的验证手段分六级（由强到弱）：",[488,932,933,946],{},[491,934,935],{},[494,936,937,940,943],{},[497,938,939],{},"验证强度",[497,941,942],{},"手段",[497,944,945],{},"可靠性",[504,947,948,961,974,986,999,1012],{},[494,949,950,955,958],{},[509,951,952],{},[36,953,954],{},"执行级",[509,956,957],{},"跑测试、编译、运行",[509,959,960],{},"★★★★★",[494,962,963,968,971],{},[509,964,965],{},[36,966,967],{},"静态分析",[509,969,970],{},"TypeScript \u002F lint \u002F AST 检查",[509,972,973],{},"★★★★",[494,975,976,981,984],{},[509,977,978],{},[36,979,980],{},"Schema 级",[509,982,983],{},"zod 校验输出结构",[509,985,973],{},[494,987,988,993,996],{},[509,989,990],{},[36,991,992],{},"LLM-as-Judge",[509,994,995],{},"另一个 LLM 评分",[509,997,998],{},"★★★",[494,1000,1001,1006,1009],{},[509,1002,1003],{},[36,1004,1005],{},"正则 \u002F 字符串匹配",[509,1007,1008],{},"关键字出现检查",[509,1010,1011],{},"★★",[494,1013,1014,1019,1022],{},[509,1015,1016],{},[36,1017,1018],{},"无验证",[509,1020,1021],{},"信模型",[509,1023,1024],{},"★",[15,1026,1027,1028,1031],{},"工程实务：",[36,1029,1030],{},"每个子任务至少要有一个 Verifier","。失败时走\"观察错误 → 修正 → 重试\"的 Critic-Actor 循环。",[15,1033,1034,1035,1038],{},"但 Verifier 的价值不只是\"成功\u002F失败\"的二元信号。",[36,1036,1037],{},"好的 Verifier 会返回结构化的失败原因","，让 LLM 能基于此修正：",[72,1040,1043],{"className":1041,"code":1042,"language":77},[75],"❌ Bad verifier:  \"测试失败\"\n✓ Good verifier:  \"测试 'should return user id' 失败：\n                   预期 'user-123'，实际 undefined。\n                   可能原因：getUserById 未处理传入的 id 参数。\"\n",[79,1044,1042],{"__ignoreMap":81},[15,1046,1047],{},"TDD 是 Verifier Loop 最自然的实现——测试就是需求的可执行版本，红 → 绿 → 重构的节奏天然适配 Agent 的工作方式。",[15,1049,1050,1052],{},[36,1051,59],{}," Verifier 是 Agent 质量的天花板。执行级验证（跑测试、编译）是最可靠的，静态分析次之。每个子任务都必须配至少一个。",[22,1054,1056],{"id":1055},"_5-state-is-the-backbone分层的状态管理","5. State is the Backbone：分层的状态管理",[15,1058,1059],{},"生产级 Agent 最核心的基础设施是状态管理。按粒度分四层：",[30,1061,1062,1068,1074,1080],{},[33,1063,1064,1067],{},[36,1065,1066],{},"任务级","：每个 subtask 的 status \u002F result \u002F errors",[33,1069,1070,1073],{},[36,1071,1072],{},"步级","：每次 LLM 调用的 input \u002F output \u002F tokens \u002F latency",[33,1075,1076,1079],{},[36,1077,1078],{},"事件级","：每个 tool call 的参数、返回、耗时",[33,1081,1082,1085],{},[36,1083,1084],{},"会话级","：全局元信息（user_id、session_id、budget_used）",[15,1087,1088],{},"一个设计良好的 Agent State，打印出来应该能让一个新加入的工程师看懂\"现在在干什么、干到哪一步了\"。",[15,1090,1091],{},"中断恢复分三个层次：",[115,1093,1094,1100,1113],{},[33,1095,1096,1099],{},[36,1097,1098],{},"Crash Recovery","：程序崩了——checkpointer 存 Redis\u002FPostgres，重启后加载",[33,1101,1102,1105,1106,1109,1110],{},[36,1103,1104],{},"Human Pause Recovery","：人工介入暂停——",[79,1107,1108],{},"interrupt()"," + ",[79,1111,1112],{},"resume",[33,1114,1115,1118],{},[36,1116,1117],{},"Long-task Resume","：跨天任务——每个子任务完成就持久化，避免重做",[15,1120,1121,1123],{},[36,1122,59],{}," 状态不只是技术细节，它是 Agent 的\"记忆脊椎\"。没有分层持久化状态的 Agent 只能处理五分钟内的任务——超出这个窗口，崩溃就等于归零。",[22,1125,1127],{"id":1126},"_6-预算控制给你的-agent-戴上三个紧箍咒","6. 预算控制：给你的 Agent 戴上三个紧箍咒",[15,1129,1130],{},"Agent 容易\"做得太久\"——在循环里不断尝试、不断消耗 token。需要在三个维度设预算：",[30,1132,1133,1139,1148],{},[33,1134,1135,1138],{},[36,1136,1137],{},"Token 预算","：累计 token 上限，超了就强制 summary 或放弃",[33,1140,1141,1144,1145],{},[36,1142,1143],{},"Step 预算","：最多循环 N 次，对应 LangGraph 的 ",[79,1146,1147],{},"recursionLimit",[33,1149,1150,1153],{},[36,1151,1152],{},"Wall-time 预算","：墙钟时间上限，用 AbortSignal 实现",[15,1155,1156,1157],{},"任一超出 → 走降级路径：部分交付、告知用户、或转交人工。",[36,1158,1159],{},"Agent 不怕失败，怕的是悄无声息地烧钱。",[15,1161,1162,1164],{},[36,1163,59],{}," 这三个预算不是可选的 optimizations——它们是生产级 Agent 的安全带。开源 demo 和闭源产品之间最大的差距往往不在模型能力，在预算控制。",[22,1166,1168],{"id":1167},"_7-错误是信号不是终点","7. 错误是信号，不是终点",[15,1170,1171,1172,1175,1176,1178],{},"初级 Harness 遇到错误 → 重试相同操作（没用）",[1173,1174],"br",{},"\n中级 Harness 遇到错误 → 换参数重试",[1173,1177],{},[36,1179,1180],{},"高级 Harness 遇到错误 → 让 LLM 看错误详情，重新规划",[15,1182,1183],{},"把错误作为上下文的一部分喂回去，是 Agent 展现\"智能\"的关键场景。这不是简单的 retry——它需要 Harness 把 error message 结构化地注入到下一轮 LLM 调用的上下文中，让模型理解\"刚才发生了什么、为什么会失败、现在该怎么调整\"。",[15,1185,1186,1188],{},[36,1187,59],{}," Agent 的智能不在于不犯错，而在于犯了错之后能看懂错误信息并调整策略。这需要 Harness 把\"错误 → 上下文 → 重新规划\"这条链路做成标配。",[22,1190,1192],{"id":1191},"_8-工具设计少即是多","8. 工具设计：少即是多",[15,1194,1195],{},"给 Agent 20 个工具 ≠ Agent 能做 20 种事。太多工具带来的问题：",[30,1197,1198,1201,1212],{},[33,1199,1200],{},"稀释注意力——每个 turn 都要过一遍选择",[33,1202,1203,1204,1207,1208,1211],{},"相似工具混淆——",[79,1205,1206],{},"read_file"," vs ",[79,1209,1210],{},"load_file"," 到底选哪个",[33,1213,1214],{},"描述互相干扰——tool A 的描述碰巧包含了 tool B 的触发词",[15,1216,1217],{},"原则：",[30,1219,1220,1226,1237],{},[33,1221,1222,1223],{},"单个 Agent 绑定的工具保持在 ",[36,1224,1225],{},"10 个以下",[33,1227,1228,1229,1232,1233,1236],{},"相似能力合并（一个 ",[79,1230,1231],{},"file_operation"," tool，用 ",[79,1234,1235],{},"op"," 参数区分读\u002F写\u002F删）",[33,1238,1239,1240,1243],{},"大工具集用",[36,1241,1242],{},"多 Agent 路由","（Supervisor 决定用哪个子 Agent，每个子 Agent 只带自己需要的工具）",[15,1245,1246,1248],{},[36,1247,59],{}," 工具设计的原则和函数设计一样——单一职责、少即是多。复杂的工具集不要扁平铺开，用 Agent 层级来组织。",[22,1250,1252],{"id":1251},"_9-observability-first不要接受黑盒","9. Observability-First：不要接受黑盒",[15,1254,1255],{},"生产 Agent 必须从第一天就接 tracing。否则 debug 全靠运气。",[15,1257,1258],{},"推荐方案：",[30,1260,1261,1267,1273],{},[33,1262,1263,1266],{},[36,1264,1265],{},"LangSmith","（LangChain 家族原生）——看每一步的 input\u002Foutput\u002F耗时",[33,1268,1269,1272],{},[36,1270,1271],{},"OpenTelemetry","（通用方案，能跟公司现有 Grafana\u002FDatadog 整合）",[33,1274,1275,1278],{},[36,1276,1277],{},"自己的 event log","（最少要有这个——jsonl 格式，每行一个事件）",[15,1280,1281],{},"至少追踪：每次 LLM 调用的 prompt\u002Ftokens\u002Flatency、每次 tool call 的参数\u002F返回\u002F耗时、每个子任务的开始\u002F完成\u002F失败。",[15,1283,1284,1286],{},[36,1285,59],{}," \"这个 Agent 为什么给出了这个答案？\"——如果没有 tracing，这个问题你永远回答不了。",[22,1288,1290],{"id":1289},"总结九条原则背后的一个核心信念","总结：九条原则背后的一个核心信念",[15,1292,1293],{},"Harness Engineering 不是什么神秘知识，它就是把这些工程常识搬到了 AI 场景里：",[115,1295,1296,1302,1308,1314,1320,1326,1332,1338,1344],{},[33,1297,1298,1301],{},[36,1299,1300],{},"Context Engineering"," — 每个 token 都为当前子任务服务",[33,1303,1304,1307],{},[36,1305,1306],{},"Workflow + Agent 混合"," — 宏观写死，微观放开",[33,1309,1310,1313],{},[36,1311,1312],{},"Plan-Then-Execute"," — 先出结构化计划，再逐项执行",[33,1315,1316,1319],{},[36,1317,1318],{},"Verifier Loop"," — 每个子任务必须有客观验证",[33,1321,1322,1325],{},[36,1323,1324],{},"Fine-grained State"," — 分层持久化，支持任意粒度恢复",[33,1327,1328,1331],{},[36,1329,1330],{},"Budget Control"," — token\u002Fstep\u002F时间三维预算，超限降级",[33,1333,1334,1337],{},[36,1335,1336],{},"Errors as Context"," — 把错误作为新信息喂回去重新规划",[33,1339,1340,1343],{},[36,1341,1342],{},"Sparse Tools"," — 少而精的工具集，复杂能力走多 Agent 路由",[33,1345,1346,1349],{},[36,1347,1348],{},"Observability-First"," — 第一天就有 tracing",[15,1351,1352],{},"如果你学过 LangGraph，会发现每一条都对应一个原生能力——StateGraph、Conditional Edge、MemorySaver、recursionLimit——Harness 不是新概念，是这些原语的组合应用。",[15,1354,1355],{},"Claude Code、Cursor、Devin 这些产品真正的护城河不在模型层，在 Harness 层。而理解了这九条原则，你就拿到了自己搭建生产级 Agent 的蓝图。",[15,1357,1358],{},[671,1359,674],{"href":673},{"title":81,"searchDepth":228,"depth":228,"links":1361},[1362,1363,1364,1365,1366,1367,1368,1369,1370,1371],{"id":744,"depth":228,"text":745},{"id":844,"depth":228,"text":845},{"id":892,"depth":228,"text":893},{"id":923,"depth":228,"text":924},{"id":1055,"depth":228,"text":1056},{"id":1126,"depth":228,"text":1127},{"id":1167,"depth":228,"text":1168},{"id":1191,"depth":228,"text":1192},{"id":1251,"depth":228,"text":1252},{"id":1289,"depth":228,"text":1290},"很多人第一次用 Claude Code 或 Cursor 时会有一种错觉：它好聪明，什么都能做。但用久了你会发现，这些产品真正厉害的地方不是模型本身——它们底层都接的是 Claude 或 GPT——而是围绕模型搭建的那一套\"脚手架\"。",{},"\u002Fblog\u002Fai-agent-harness-engineering",{"title":715,"description":1372},"blog\u002Fai-agent-harness-engineering",[1378,1379,1380,1381,1382],"AI Agent","Harness Engineering","LangGraph","工程化","LLM","K0vtNQ4LO7pBgLid5SIVQdXoUh7dHxtKD0g9QxZHCfU",{"id":1385,"title":1386,"body":1387,"category":698,"date":699,"description":1394,"extension":700,"meta":2323,"navigation":702,"path":2324,"seo":2325,"stem":2326,"tags":2327,"__hash__":2333},"blog\u002Fblog\u002Fclaude-code-ecosystem.md","Claude Code 可编程生态：Skills、MCP 与 Hook 体系全解",{"type":8,"value":1388,"toc":2307},[1389,1392,1395,1402,1406,1412,1415,1447,1451,1455,1466,1469,1475,1478,1556,1562,1566,1608,1611,1630,1635,1640,1644,1651,1655,1661,1745,1754,1777,1782,1786,1792,1795,1855,1858,1964,1974,1979,1983,1986,2060,2066,2147,2161,2166,2170,2177,2218,2232,2236,2239,2288,2290,2297,2300,2304],[11,1390,1386],{"id":1391},"claude-code-可编程生态skillsmcp-与-hook-体系全解",[15,1393,1394],{},"Claude Code 上手一两周后，你大概率会遇到同一个瓶颈：每次都要手动描述内部框架的用法、每次都要提醒它\"别用 npm，用 pnpm\"、每次改完代码都要自己跑一遍 typecheck。",[15,1396,1397,1398,1401],{},"CC 提供了五件套来解决这个问题：",[36,1399,1400],{},"Skills、Plugins、Subagents、MCP、Hooks","。很多人把它们混为一谈，其实一个是\"知识\u002FSOP\"，一个是\"打包分发单位\"，一个是\"隔离执行角色\"，一个是\"外部系统连接器\"，一个是\"事件触发器\"。这篇逐一拆解。",[22,1403,1405],{"id":1404},"_1-五件套的关系一张图看清","1. 五件套的关系（一张图看清）",[72,1407,1410],{"className":1408,"code":1409,"language":77},[75],"        ┌────────── Plugin (分发\u002F安装单位) ──────────┐\n        │                                             │\n        │ 可包含：Skills + Subagents + MCP + Hooks    │\n        │          + Slash commands                    │\n        └─────────────────────────────────────────────┘\n\nSkill    = 一份 SKILL.md，告诉 CC \"遇到 X 场景该怎么做\" (SOP)\nSubagent = 一个专门角色 (只读探索 \u002F 测试执行 \u002F 代码审查)\nMCP      = 连接外部系统 (数据库 \u002F Jira \u002F 监控 \u002F wiki)\nHook     = 事件钩子 (编辑前后、工具调用前后触发脚本)\n",[79,1411,1409],{"__ignoreMap":81},[15,1413,1414],{},"结论直给：",[30,1416,1417,1423,1429,1435,1441],{},[33,1418,1419,1420],{},"\"我要让 CC 在遇到 X 场景时按 Y 步骤做\" → 写 ",[36,1421,1422],{},"Skill",[33,1424,1425,1426],{},"\"我要让 CC 连上公司 Jira\u002F监控\u002F数据库\" → 配 ",[36,1427,1428],{},"MCP",[33,1430,1431,1432],{},"\"我要一个只读探索、不污染主上下文的角色\" → 造 ",[36,1433,1434],{},"Subagent",[33,1436,1437,1438],{},"\"我要每次改代码后自动跑 lint\" → 配 ",[36,1439,1440],{},"Hook",[33,1442,1443,1444],{},"\"我要把以上几样打包分发给团队\" → 打成 ",[36,1445,1446],{},"Plugin",[22,1448,1450],{"id":1449},"_2-skills按需注入的-sop","2. Skills：按需注入的 SOP",[410,1452,1454],{"id":1453},"skill-的本质","Skill 的本质",[15,1456,1457,1458,1461,1462,1465],{},"一个 Skill 就是一个目录，里面至少有一个 ",[79,1459,1460],{},"SKILL.md","，前置 frontmatter 声明名字和触发描述。CC 在处理任务时扫描所有可用 Skills 的描述，",[36,1463,1464],{},"按需加载","——这是核心价值：不常驻上下文，只在相关时注入。",[15,1467,1468],{},"最小骨架：",[72,1470,1473],{"className":1471,"code":1472,"language":77},[75],"my-skill\u002F\n├── SKILL.md            # 必需\n├── templates\u002F          # 可选：代码模板\n├── scripts\u002F            # 可选：辅助脚本\n└── references\u002F         # 可选：详细文档（按需再读）\n",[79,1474,1472],{"__ignoreMap":81},[15,1476,1477],{},"SKILL.md 示例：",[72,1479,1483],{"className":1480,"code":1481,"language":1482,"meta":81,"style":81},"language-markdown shiki shiki-themes github-dark","---\nname: internal-rpc-handler\ndescription: |\n  创建或修改公司内部 InternalRPC 框架的 handler。\n  USE WHEN: 用户要求添加 RPC 接口、涉及 @company\u002Frpc 相关代码。\n  DO NOT USE FOR: 外部 HTTP API（用 rest-api skill）。\nallowed-tools: Read Edit Bash(pnpm test:rpc *)\n---\n\n# InternalRPC Handler 创建规范\n\n## 步骤\n1. 在 `packages\u002Frpc\u002Fhandlers\u002F` 下创建 `\u003Cname>.handler.ts`\n2. 继承 `BaseHandler`，实现 `handle(ctx, req)` ...\n","markdown",[79,1484,1485,1490,1495,1500,1505,1510,1515,1520,1524,1529,1534,1538,1544,1550],{"__ignoreMap":81},[203,1486,1487],{"class":205,"line":206},[203,1488,1489],{},"---\n",[203,1491,1492],{"class":205,"line":228},[203,1493,1494],{},"name: internal-rpc-handler\n",[203,1496,1497],{"class":205,"line":250},[203,1498,1499],{},"description: |\n",[203,1501,1502],{"class":205,"line":279},[203,1503,1504],{},"  创建或修改公司内部 InternalRPC 框架的 handler。\n",[203,1506,1507],{"class":205,"line":324},[203,1508,1509],{},"  USE WHEN: 用户要求添加 RPC 接口、涉及 @company\u002Frpc 相关代码。\n",[203,1511,1512],{"class":205,"line":330},[203,1513,1514],{},"  DO NOT USE FOR: 外部 HTTP API（用 rest-api skill）。\n",[203,1516,1517],{"class":205,"line":336},[203,1518,1519],{},"allowed-tools: Read Edit Bash(pnpm test:rpc *)\n",[203,1521,1522],{"class":205,"line":348},[203,1523,1489],{},[203,1525,1526],{"class":205,"line":359},[203,1527,1528],{"emptyLinePlaceholder":702},"\n",[203,1530,1531],{"class":205,"line":377},[203,1532,1533],{},"# InternalRPC Handler 创建规范\n",[203,1535,1536],{"class":205,"line":383},[203,1537,1528],{"emptyLinePlaceholder":702},[203,1539,1541],{"class":205,"line":1540},12,[203,1542,1543],{},"## 步骤\n",[203,1545,1547],{"class":205,"line":1546},13,[203,1548,1549],{},"1. 在 `packages\u002Frpc\u002Fhandlers\u002F` 下创建 `\u003Cname>.handler.ts`\n",[203,1551,1553],{"class":205,"line":1552},14,[203,1554,1555],{},"2. 继承 `BaseHandler`，实现 `handle(ctx, req)` ...\n",[15,1557,1558,1561],{},[36,1559,1560],{},"关键：description 写得越具体、触发条件越清晰，CC 越准确地知道什么时候加载它。"," 建议用 USE WHEN \u002F DO NOT USE FOR 两段式。",[410,1563,1565],{"id":1564},"写-skill-的五条黄金法则","写 Skill 的五条黄金法则",[115,1567,1568,1574,1587,1593,1599],{},[33,1569,1570,1573],{},[36,1571,1572],{},"description 是索引","：把用户可能说的话、可能触发的文件类型全写进去",[33,1575,1576,1579,1580,1583,1584],{},[36,1577,1578],{},"SKILL.md 自己精简","：核心 SOP 放主文件，大段示例\u002F模板放 ",[79,1581,1582],{},"templates\u002F","、",[79,1585,1586],{},"references\u002F",[33,1588,1589,1592],{},[36,1590,1591],{},"写命令清单而不是散文","：\"Step 1 → Step 2\" 的 checklist 比大段说明有效",[33,1594,1595,1598],{},[36,1596,1597],{},"包含反例","：\"不要这样做\"比\"要这样做\"更能防止事故",[33,1600,1601,1604,1605,309],{},[36,1602,1603],{},"绑定到可验证的产物","：例如\"生成后必须跑 ",[79,1606,1607],{},"pnpm test:rpc",[410,1609,1610],{"id":1610},"放在哪里",[30,1612,1613,1620,1627],{},[33,1614,1615,1616,1619],{},"个人全局：",[79,1617,1618],{},"~\u002F.claude\u002Fskills\u002F\u003Cname>\u002FSKILL.md","（只对你生效）",[33,1621,1622,1623,1626],{},"项目级：",[79,1624,1625],{},".claude\u002Fskills\u002F\u003Cname>\u002FSKILL.md","（随仓库提交，团队共享）",[33,1628,1629],{},"通过 Plugin 分发：跨项目共享",[15,1631,1632],{},[36,1633,1634],{},"强烈建议：团队约定的东西走项目级（进 git），个人习惯走全局。",[15,1636,1637,1639],{},[36,1638,59],{}," Skills 是整个 CC 可编程体系里 ROI 最高的部分——零运维成本，纯 markdown，写完就生效。内部框架越闭源、团队规范越特殊，Skills 的价值越大。",[22,1641,1643],{"id":1642},"_3-subagents保护主会话上下文的隔离执行","3. Subagents：保护主会话上下文的隔离执行",[15,1645,1646,1647,1650],{},"主会话的上下文是最宝贵的资源。把一个任务派给 subagent 去跑——比如\"扫描 200 个文件找出所有用了老配置的地方\"——它会用光自己的上下文，但",[36,1648,1649],{},"只把摘要返回","给你。主会话还是干净的，继续推进高层决策。",[410,1652,1654],{"id":1653},"定义一个-subagent","定义一个 Subagent",[15,1656,1657,1658],{},"路径：",[79,1659,1660],{},".claude\u002Fagents\u002F\u003Cname>.md",[72,1662,1664],{"className":1480,"code":1663,"language":1482,"meta":81,"style":81},"---\nname: code-explorer\ndescription: 只读代码探索；用于快速回答\"X 功能在哪实现\"\ntools: Read, Grep, Glob\nmodel: haiku                   # 探索用 Haiku 4.5，又快又便宜\nisolation: worktree            # 在临时 worktree 里跑，零改动自动清理\npermissionMode: plan           # 强制只读\nmaxTurns: 30\neffort: low\n---\n\n你是代码考古专家。硬规则：\n1. 只读，不改任何文件\n2. 输出结构化：文件清单 \u002F 关键函数 \u002F 调用关系\n3. 不要把大段源码贴回主会话，用\"文件:行号\"\n4. 不确定的地方标 UNKNOWN，不要猜\n",[79,1665,1666,1670,1675,1680,1685,1690,1695,1700,1705,1710,1714,1718,1723,1728,1733,1739],{"__ignoreMap":81},[203,1667,1668],{"class":205,"line":206},[203,1669,1489],{},[203,1671,1672],{"class":205,"line":228},[203,1673,1674],{},"name: code-explorer\n",[203,1676,1677],{"class":205,"line":250},[203,1678,1679],{},"description: 只读代码探索；用于快速回答\"X 功能在哪实现\"\n",[203,1681,1682],{"class":205,"line":279},[203,1683,1684],{},"tools: Read, Grep, Glob\n",[203,1686,1687],{"class":205,"line":324},[203,1688,1689],{},"model: haiku                   # 探索用 Haiku 4.5，又快又便宜\n",[203,1691,1692],{"class":205,"line":330},[203,1693,1694],{},"isolation: worktree            # 在临时 worktree 里跑，零改动自动清理\n",[203,1696,1697],{"class":205,"line":336},[203,1698,1699],{},"permissionMode: plan           # 强制只读\n",[203,1701,1702],{"class":205,"line":348},[203,1703,1704],{},"maxTurns: 30\n",[203,1706,1707],{"class":205,"line":359},[203,1708,1709],{},"effort: low\n",[203,1711,1712],{"class":205,"line":377},[203,1713,1489],{},[203,1715,1716],{"class":205,"line":383},[203,1717,1528],{"emptyLinePlaceholder":702},[203,1719,1720],{"class":205,"line":1540},[203,1721,1722],{},"你是代码考古专家。硬规则：\n",[203,1724,1725],{"class":205,"line":1546},[203,1726,1727],{},"1. 只读，不改任何文件\n",[203,1729,1730],{"class":205,"line":1552},[203,1731,1732],{},"2. 输出结构化：文件清单 \u002F 关键函数 \u002F 调用关系\n",[203,1734,1736],{"class":205,"line":1735},15,[203,1737,1738],{},"3. 不要把大段源码贴回主会话，用\"文件:行号\"\n",[203,1740,1742],{"class":205,"line":1741},16,[203,1743,1744],{},"4. 不确定的地方标 UNKNOWN，不要猜\n",[15,1746,1747,900,1750,1753],{},[36,1748,1749],{},"关键坑",[79,1751,1752],{},"tools"," 字段省略 = 继承全部工具。想真正限制权限必须显式写白名单。",[15,1755,1756,1757,1760,1761,1764,1765,1768,1769,1772,1773,1776],{},"CC 自带几个内置 subagent：",[79,1758,1759],{},"Explore","（只读探索）、",[79,1762,1763],{},"Plan","（出实施计划）、",[79,1766,1767],{},"code-reviewer","（阶段性收尾 review）、",[79,1770,1771],{},"general-purpose","（兜底）。日常用法很简单——自然语言：\"让 code-explorer 去找所有调用 ",[79,1774,1775],{},"PaymentService.charge"," 的地方，只返回清单。\"",[15,1778,1779,1781],{},[36,1780,59],{}," Subagent 解决的核心问题是上下文预算隔离。主会话开 Sonnet\u002FOpus 做高层决策，脏活累活派给 Haiku subagent 去跑——成本降一个量级，主会话永远清爽。",[22,1783,1785],{"id":1784},"_4-mcp把内部系统安全地接进-agent","4. MCP：把内部系统安全地接进 Agent",[15,1787,1788,1789,731],{},"MCP (Model Context Protocol) 是一套让 Agent 安全调用外部工具\u002F数据源的协议。对资深工程师而言，MCP 的意义是：",[36,1790,1791],{},"终于可以让 CC 安全地\"看到\"公司内部系统，而不是把敏感数据贴进 prompt",[15,1793,1794],{},"MCP server 提供三类能力（很多教程只讲 tools，漏了后两者）：",[488,1796,1797,1810],{},[491,1798,1799],{},[494,1800,1801,1804,1807],{},[497,1802,1803],{},"能力",[497,1805,1806],{},"含义",[497,1808,1809],{},"典型用法",[504,1811,1812,1825,1842],{},[494,1813,1814,1819,1822],{},[509,1815,1816],{},[36,1817,1818],{},"Tools",[509,1820,1821],{},"Agent 能调用的函数",[509,1823,1824],{},"查 Jira、跑 SQL、发 PR comment",[494,1826,1827,1832,1835],{},[509,1828,1829],{},[36,1830,1831],{},"Resources",[509,1833,1834],{},"Agent 能读取的数据",[509,1836,1837,1838,1841],{},"把内部 wiki\u002F设计文档当 ",[79,1839,1840],{},"@"," 引用",[494,1843,1844,1849,1852],{},[509,1845,1846],{},[36,1847,1848],{},"Prompts",[509,1850,1851],{},"可复用的 prompt 模板",[509,1853,1854],{},"团队共享的\"按规范生成 RFC\"",[15,1856,1857],{},"安装命令（推荐用 CLI 而不是手写 JSON）：",[72,1859,1863],{"className":1860,"code":1861,"language":1862,"meta":81,"style":81},"language-bash shiki shiki-themes github-dark","# stdio 类（本地子进程）\nclaude mcp add --transport stdio playwright -- npx -y @playwright\u002Fmcp@latest\n\n# HTTP 类（远端服务）\nclaude mcp add --transport http sentry https:\u002F\u002Fmcp.sentry.dev\u002Fmcp\n\n# 团队共享：加 --scope project，写入 .mcp.json 进 git\nclaude mcp add --transport http rpc-docs --scope project https:\u002F\u002Fmcp.internal\u002Fmcp\n","bash",[79,1864,1865,1871,1903,1907,1912,1931,1935,1940],{"__ignoreMap":81},[203,1866,1867],{"class":205,"line":206},[203,1868,1870],{"class":1869},"sAwPA","# stdio 类（本地子进程）\n",[203,1872,1873,1876,1879,1882,1885,1888,1891,1894,1897,1900],{"class":205,"line":228},[203,1874,1875],{"class":220},"claude",[203,1877,1878],{"class":308}," mcp",[203,1880,1881],{"class":308}," add",[203,1883,1884],{"class":213}," --transport",[203,1886,1887],{"class":308}," stdio",[203,1889,1890],{"class":308}," playwright",[203,1892,1893],{"class":213}," --",[203,1895,1896],{"class":308}," npx",[203,1898,1899],{"class":213}," -y",[203,1901,1902],{"class":308}," @playwright\u002Fmcp@latest\n",[203,1904,1905],{"class":205,"line":250},[203,1906,1528],{"emptyLinePlaceholder":702},[203,1908,1909],{"class":205,"line":279},[203,1910,1911],{"class":1869},"# HTTP 类（远端服务）\n",[203,1913,1914,1916,1918,1920,1922,1925,1928],{"class":205,"line":324},[203,1915,1875],{"class":220},[203,1917,1878],{"class":308},[203,1919,1881],{"class":308},[203,1921,1884],{"class":213},[203,1923,1924],{"class":308}," http",[203,1926,1927],{"class":308}," sentry",[203,1929,1930],{"class":308}," https:\u002F\u002Fmcp.sentry.dev\u002Fmcp\n",[203,1932,1933],{"class":205,"line":330},[203,1934,1528],{"emptyLinePlaceholder":702},[203,1936,1937],{"class":205,"line":336},[203,1938,1939],{"class":1869},"# 团队共享：加 --scope project，写入 .mcp.json 进 git\n",[203,1941,1942,1944,1946,1948,1950,1952,1955,1958,1961],{"class":205,"line":348},[203,1943,1875],{"class":220},[203,1945,1878],{"class":308},[203,1947,1881],{"class":308},[203,1949,1884],{"class":213},[203,1951,1924],{"class":308},[203,1953,1954],{"class":308}," rpc-docs",[203,1956,1957],{"class":213}," --scope",[203,1959,1960],{"class":308}," project",[203,1962,1963],{"class":308}," https:\u002F\u002Fmcp.internal\u002Fmcp\n",[15,1965,1966,1969,1970,1973],{},[36,1967,1968],{},"安全三原则","：只读连接优先、用环境变量而不是明文 token、限制 ",[79,1971,1972],{},"allowedTools"," 防止越权。",[15,1975,1976,1978],{},[36,1977,59],{}," MCP 是 CC 从\"单机工具\"升级到\"企业级 Agent\"的关键一步。优先接入 GitHub\u002FJira（工作流闭环）、DB 只读连接（让 CC 看 schema 写 SQL 质量直线上升）、内部 wiki（架构文档随手可查）。",[22,1980,1982],{"id":1981},"_5-hooks事件驱动的自动化护栏","5. Hooks：事件驱动的自动化护栏",[15,1984,1985],{},"在以下时机自动跑脚本（约 29 个事件，挑最常用的）：",[488,1987,1988,2000],{},[491,1989,1990],{},[494,1991,1992,1995,1998],{},[497,1993,1994],{},"事件",[497,1996,1997],{},"触发时机",[497,1999,1809],{},[504,2001,2002,2015,2034,2047],{},[494,2003,2004,2009,2012],{},[509,2005,2006],{},[79,2007,2008],{},"PostToolUse",[509,2010,2011],{},"CC 调用工具后",[509,2013,2014],{},"改代码后自动 typecheck + lint",[494,2016,2017,2022,2025],{},[509,2018,2019],{},[79,2020,2021],{},"PreToolUse",[509,2023,2024],{},"CC 调用工具前",[509,2026,2027,2028,1583,2031],{},"拦截 ",[79,2029,2030],{},"rm -rf",[79,2032,2033],{},"git push -f",[494,2035,2036,2041,2044],{},[509,2037,2038],{},[79,2039,2040],{},"SessionStart",[509,2042,2043],{},"会话开始",[509,2045,2046],{},"注入环境信息",[494,2048,2049,2054,2057],{},[509,2050,2051],{},[79,2052,2053],{},"Stop",[509,2055,2056],{},"会话结束",[509,2058,2059],{},"提醒沉淀 CLAUDE.md",[15,2061,2062,2063,900],{},"最有价值的 Hook 配置——",[36,2064,2065],{},"自动反馈环",[72,2067,2071],{"className":2068,"code":2069,"language":2070,"meta":81,"style":81},"language-jsonc shiki shiki-themes github-dark","{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Edit|Write\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"pnpm -s typecheck && pnpm -s lint --max-warnings 0 || exit 2\"\n          }\n        ]\n      }\n    ]\n  }\n}\n","jsonc",[79,2072,2073,2078,2083,2088,2093,2098,2103,2108,2113,2118,2123,2128,2133,2138,2142],{"__ignoreMap":81},[203,2074,2075],{"class":205,"line":206},[203,2076,2077],{},"{\n",[203,2079,2080],{"class":205,"line":228},[203,2081,2082],{},"  \"hooks\": {\n",[203,2084,2085],{"class":205,"line":250},[203,2086,2087],{},"    \"PostToolUse\": [\n",[203,2089,2090],{"class":205,"line":279},[203,2091,2092],{},"      {\n",[203,2094,2095],{"class":205,"line":324},[203,2096,2097],{},"        \"matcher\": \"Edit|Write\",\n",[203,2099,2100],{"class":205,"line":330},[203,2101,2102],{},"        \"hooks\": [\n",[203,2104,2105],{"class":205,"line":336},[203,2106,2107],{},"          {\n",[203,2109,2110],{"class":205,"line":348},[203,2111,2112],{},"            \"type\": \"command\",\n",[203,2114,2115],{"class":205,"line":359},[203,2116,2117],{},"            \"command\": \"pnpm -s typecheck && pnpm -s lint --max-warnings 0 || exit 2\"\n",[203,2119,2120],{"class":205,"line":377},[203,2121,2122],{},"          }\n",[203,2124,2125],{"class":205,"line":383},[203,2126,2127],{},"        ]\n",[203,2129,2130],{"class":205,"line":1540},[203,2131,2132],{},"      }\n",[203,2134,2135],{"class":205,"line":1546},[203,2136,2137],{},"    ]\n",[203,2139,2140],{"class":205,"line":1552},[203,2141,380],{},[203,2143,2144],{"class":205,"line":1735},[203,2145,2146],{},"}\n",[15,2148,2149,2150,2153,2154,2160],{},"效果：CC 每次改完 ",[79,2151,2152],{},".ts"," 文件，自动跑 typecheck。",[36,2155,2156,2159],{},[79,2157,2158],{},"exit 2"," 是关键","——它表示阻塞错误，stderr 会反馈给 CC 让它自己修。这是从\"人手动验证\"到\"Agent 自我纠正\"的质变。每个有类型系统的项目都应该配一个。",[15,2162,2163,2165],{},[36,2164,59],{}," Hooks 是基础设施层的\"护栏\"——不是用来教 CC 怎么干活，而是防止它搞破坏。typecheck hook + 危险命令拦截 = 基本的安全网。",[22,2167,2169],{"id":2168},"_6-plugins打包分发上述所有能力","6. Plugins：打包分发上述所有能力",[15,2171,2172,2173,2176],{},"Plugin 就是 Skills\u002FSubagents\u002FMCP\u002FHooks 的打包壳子，带 ",[79,2174,2175],{},"plugin.json"," 元数据，通过 marketplace 分发。安装：",[72,2178,2180],{"className":1860,"code":2179,"language":1862,"meta":81,"style":81},"\u002Fplugin marketplace add anthropics\u002Fclaude-code    # 加 marketplace\n\u002Fplugin install github@claude-plugins-official    # 装具体 plugin\n\u002Fplugin                                          # 打开交互界面\n",[79,2181,2182,2198,2211],{"__ignoreMap":81},[203,2183,2184,2187,2190,2192,2195],{"class":205,"line":206},[203,2185,2186],{"class":220},"\u002Fplugin",[203,2188,2189],{"class":308}," marketplace",[203,2191,1881],{"class":308},[203,2193,2194],{"class":308}," anthropics\u002Fclaude-code",[203,2196,2197],{"class":1869},"    # 加 marketplace\n",[203,2199,2200,2202,2205,2208],{"class":205,"line":228},[203,2201,2186],{"class":220},[203,2203,2204],{"class":308}," install",[203,2206,2207],{"class":308}," github@claude-plugins-official",[203,2209,2210],{"class":1869},"    # 装具体 plugin\n",[203,2212,2213,2215],{"class":205,"line":250},[203,2214,2186],{"class":220},[203,2216,2217],{"class":1869},"                                          # 打开交互界面\n",[15,2219,2220,2223,2224,2227,2228,2231],{},[36,2221,2222],{},"选型建议","：只是自己\u002F一个仓库用 → 直接放 ",[79,2225,2226],{},".claude\u002Fskills\u002F"," 或 ",[79,2229,2230],{},".claude\u002Fagents\u002F"," 即可，不要打包 plugin。跨多个仓库复用 → 才打成 plugin，放到公司内部 git。",[22,2233,2235],{"id":2234},"推荐引入顺序按-roi团队级","推荐引入顺序（按 ROI，团队级）",[15,2237,2238],{},"对于一个 5-20 人的后端\u002F全栈团队：",[115,2240,2241,2247,2258,2264,2270,2276,2282],{},[33,2242,2243,2246],{},[36,2244,2245],{},"项目级 CLAUDE.md","（0 成本，立刻有效）",[33,2248,2249,900,2252,1583,2255],{},[36,2250,2251],{},"1-2 个 Subagent",[79,2253,2254],{},"code-explorer",[79,2256,2257],{},"test-runner",[33,2259,2260,2263],{},[36,2261,2262],{},"PostToolUse typecheck\u002Flint Hook","（挡掉 70% 低级错误）",[33,2265,2266,2269],{},[36,2267,2268],{},"2-5 个内部框架 Skill","（公司越闭源 ROI 越高）",[33,2271,2272,2275],{},[36,2273,2274],{},"GitHub \u002F Jira MCP","（工作流闭环）",[33,2277,2278,2281],{},[36,2279,2280],{},"DB 只读 MCP","（让 CC 看 schema）",[33,2283,2284,2287],{},[36,2285,2286],{},"把上面打包成内部 Plugin","，新人 onboard 一条命令装完",[22,2289,648],{"id":648},[15,2291,2292,2293,2296],{},"CC 的可编程体系本质上做三件事：",[36,2294,2295],{},"灌上下文（Skills）、装能力（MCP\u002FSubagents）、定规则（Hooks\u002FCLAUDE.md）","。理解了这个框架，你就知道每个新需求该往哪个方向走。",[15,2298,2299],{},"最重要的是：不要一开始全上。先配 typecheck hook 和 1-2 个 Skill，把基础打牢，再按需扩展。插件装得越多不等于越强——每个 Skill\u002FHook 都消耗 attention。少而精。",[15,2301,2302],{},[671,2303,674],{"href":673},[676,2305,2306],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}",{"title":81,"searchDepth":228,"depth":228,"links":2308},[2309,2310,2315,2318,2319,2320,2321,2322],{"id":1404,"depth":228,"text":1405},{"id":1449,"depth":228,"text":1450,"children":2311},[2312,2313,2314],{"id":1453,"depth":250,"text":1454},{"id":1564,"depth":250,"text":1565},{"id":1610,"depth":250,"text":1610},{"id":1642,"depth":228,"text":1643,"children":2316},[2317],{"id":1653,"depth":250,"text":1654},{"id":1784,"depth":228,"text":1785},{"id":1981,"depth":228,"text":1982},{"id":2168,"depth":228,"text":2169},{"id":2234,"depth":228,"text":2235},{"id":648,"depth":228,"text":648},{},"\u002Fblog\u002Fclaude-code-ecosystem",{"title":1386,"description":1394},"blog\u002Fclaude-code-ecosystem",[2328,2329,1428,2330,2331,2332],"Claude Code","Skills","Plugins","Hooks","AI编程","VaSLsSFiOtPMQHx4I0A-J3YhF3B7Q7ix3DW76Ftu9P4",{"id":2335,"title":2336,"body":2337,"category":698,"date":699,"description":3042,"extension":700,"meta":3043,"navigation":702,"path":3044,"seo":3045,"stem":3046,"tags":3047,"__hash__":3050},"blog\u002Fblog\u002Fclaude-code-team-adoption.md","让 Claude Code 读懂你的代码库：CLAUDE.md 分层与团队落地实践",{"type":8,"value":2338,"toc":3019},[2339,2342,2349,2355,2359,2362,2376,2382,2385,2388,2457,2463,2466,2469,2497,2503,2508,2516,2526,2568,2615,2618,2626,2630,2637,2685,2694,2703,2707,2710,2714,2717,2723,2730,2734,2737,2741,2744,2771,2775,2778,2803,2809,2813,2816,2841,2847,2851,2854,2859,2863,2867,2873,2877,2883,2889,2894,2898,2981,2983,2986,3009,3012,3016],[11,2340,2336],{"id":2341},"让-claude-code-读懂你的代码库claudemd-分层与团队落地实践",[15,2343,2344,2345,2348],{},"Claude Code 最大的优势是它有工具、能改代码。但它最大的盲区也很明显：它不认识你们公司的内部框架，不知道你们团队三年沉淀下来的\"不写进文档的约定\"，更不懂那个 2000 行的 ",[79,2346,2347],{},"legacy-pricing.ts"," 为什么碰不得。",[15,2350,2351,2352,731],{},"所有这些隐性知识，都需要你主动编码进 CC 的\"记忆系统\"。核心载体就是 CLAUDE.md——但这不意味着把所有东西塞进一个文件。真正高效的做法是",[36,2353,2354],{},"分层设计",[22,2356,2358],{"id":2357},"_1-不是只有一个-claudemd","1. 不是只有一个 CLAUDE.md",[15,2360,2361],{},"CC 的 CLAUDE.md 加载有两层逻辑：",[30,2363,2364,2370],{},[33,2365,2366,2369],{},[36,2367,2368],{},"向上聚合","（启动时一次性）：从当前目录一路向上找所有 CLAUDE.md，全部加载",[33,2371,2372,2375],{},[36,2373,2374],{},"向下按需","（运行时增量）：当 CC 操作某个子目录里的文件时，那子目录链路上的 CLAUDE.md 自动追加",[72,2377,2380],{"className":2378,"code":2379,"language":77},[75],"~\u002F.claude\u002FCLAUDE.md                  # 全局（你个人跨所有项目的偏好）\n\u003Crepo>\u002FCLAUDE.md                     # 项目级（启动时加载）\n\u003Crepo>\u002Fbackend\u002FCLAUDE.md             # CC 操作 backend\u002F 下文件时按需追加\n\u003Crepo>\u002Fbackend\u002Fbilling\u002FCLAUDE.md     # 操作 billing\u002F 下文件时再追加\n",[79,2381,2379],{"__ignoreMap":81},[15,2383,2384],{},"为什么根 CLAUDE.md 不够用？一条规则可能只对计费模块适用（\"金额一律 Decimal，禁止 JS number\"）——写进根会让它常驻所有会话，浪费 token。",[410,2386,2387],{"id":2387},"推荐四层结构",[488,2389,2390,2403],{},[491,2391,2392],{},[494,2393,2394,2397,2400],{},[497,2395,2396],{},"层级",[497,2398,2399],{},"文件",[497,2401,2402],{},"内容",[504,2404,2405,2418,2431,2444],{},[494,2406,2407,2410,2415],{},[509,2408,2409],{},"全局",[509,2411,2412],{},[79,2413,2414],{},"~\u002F.claude\u002FCLAUDE.md",[509,2416,2417],{},"个人偏好：commit 风格、默认语言",[494,2419,2420,2423,2428],{},[509,2421,2422],{},"项目",[509,2424,2425],{},[79,2426,2427],{},"\u003Crepo>\u002FCLAUDE.md",[509,2429,2430],{},"铁律 + 目录地图 + Skills 索引 + 风格锚点",[494,2432,2433,2436,2441],{},[509,2434,2435],{},"子系统",[509,2437,2438],{},[79,2439,2440],{},"\u003Crepo>\u002F\u003Carea>\u002FCLAUDE.md",[509,2442,2443],{},"该子系统特有架构、依赖、命令",[494,2445,2446,2449,2454],{},[509,2447,2448],{},"模块",[509,2450,2451],{},[79,2452,2453],{},"\u003Crepo>\u002F\u003Carea>\u002F\u003Cmodule>\u002FCLAUDE.md",[509,2455,2456],{},"历史坑、兼容约束、\"动这里前先看 X\"",[15,2458,2459,2462],{},[36,2460,2461],{},"原则：越模块化、越专有的规则越往深层子目录放；只有全局铁律才进根。"," 否则根 CLAUDE.md 迅速膨胀，无关会话也要为它付 token。",[410,2464,2465],{"id":2465},"维护策略",[15,2467,2468],{},"CC 不会自动更新 CLAUDE.md——这是故意的，因为记忆文件会常驻上下文、影响后续所有会话。日常更新走四种方式：",[30,2470,2471,2481,2488,2494],{},[33,2472,2473,2476,2477,2480],{},[79,2474,2475],{},"#"," 前缀：会话里直接发 ",[79,2478,2479],{},"# Billing 模块金额一律用 Decimal","，最顺手",[33,2482,2483,2484,2487],{},"自然语言：\"把刚才关于 X 的决策追加到 ",[79,2485,2486],{},"services\u002Fbilling\u002FCLAUDE.md"," 的踩坑记录一节\"",[33,2489,2490,2493],{},[79,2491,2492],{},"\u002Fmemory","：打开专用编辑视图",[33,2495,2496],{},"直接编辑文件：大范围重构",[15,2498,2499,2502],{},[36,2500,2501],{},"什么值得回写？"," 你在不同会话里对 CC 讲过同一件事 ≥ 2 次、发现了一条希望未来所有改动都遵守的约束、修 bug 时挖出的历史坑。",[15,2504,2505,2507],{},[36,2506,59],{}," CLAUDE.md 不是一次写完的，是踩坑攒出来的。发现 CC 偏了、发现它不知道某条历史包袱 → 立刻回写到最合适的那一层。最佳时机是任务刚结束，而不是\"等以后集中整理\"。",[22,2509,2511,2512,2515],{"id":2510},"_2-clauderules另一种切分维度","2. ",[79,2513,2514],{},".claude\u002Frules\u002F","：另一种切分维度",[15,2517,2518,2519,2521,2522,2525],{},"当规则更适合按\"文件类型\"而不是\"业务模块\"组织时，用 ",[79,2520,2514],{},"。它支持 ",[79,2523,2524],{},"paths"," frontmatter 做路径作用域——只有 CC 读到匹配的文件时才加载：",[72,2527,2529],{"className":1480,"code":2528,"language":1482,"meta":81,"style":81},"---\npaths:\n  - \"src\u002Fapi\u002F**\u002F*.ts\"\n---\n\n# API 开发规范\n- 所有入口必须先做 zod 校验\n- 错误用 AppError，不抛裸 Error\n",[79,2530,2531,2535,2540,2545,2549,2553,2558,2563],{"__ignoreMap":81},[203,2532,2533],{"class":205,"line":206},[203,2534,1489],{},[203,2536,2537],{"class":205,"line":228},[203,2538,2539],{},"paths:\n",[203,2541,2542],{"class":205,"line":250},[203,2543,2544],{},"  - \"src\u002Fapi\u002F**\u002F*.ts\"\n",[203,2546,2547],{"class":205,"line":279},[203,2548,1489],{},[203,2550,2551],{"class":205,"line":324},[203,2552,1528],{"emptyLinePlaceholder":702},[203,2554,2555],{"class":205,"line":330},[203,2556,2557],{},"# API 开发规范\n",[203,2559,2560],{"class":205,"line":336},[203,2561,2562],{},"- 所有入口必须先做 zod 校验\n",[203,2564,2565],{"class":205,"line":348},[203,2566,2567],{},"- 错误用 AppError，不抛裸 Error\n",[488,2569,2570,2582],{},[491,2571,2572],{},[494,2573,2574,2579],{},[497,2575,2576,2577],{},"用 ",[79,2578,2514],{},[497,2580,2581],{},"用子目录 CLAUDE.md",[504,2583,2584,2599,2607],{},[494,2585,2586,2596],{},[509,2587,2588,2589,1583,2592,2595],{},"规则按 glob 模式组织（",[79,2590,2591],{},"*.test.ts",[79,2593,2594],{},"migrations\u002F**","）",[509,2597,2598],{},"规则按业务模块边界组织",[494,2600,2601,2604],{},[509,2602,2603],{},"同类规则跨多个目录复用",[509,2605,2606],{},"模块级\"动这里前先看 X\"",[494,2608,2609,2612],{},[509,2610,2611],{},"细到\"只在改 React 组件时加载\"",[509,2613,2614],{},"模块级全套规范",[15,2616,2617],{},"两套机制可以并存。关键区别：rule 是常驻片段（匹配时整段注入 system prompt），Skill 是按需触发（正文只在调用时才加载）。不要把 SOP 塞进 rules——会无谓占 token。",[15,2619,2620,2622,2623,2625],{},[36,2621,59],{}," CLAUDE.md 管\"这个模块的规矩\"，",[79,2624,2514],{}," 管\"这类文件的规矩\"。两者配合才能覆盖大仓的全部场景。",[22,2627,2629],{"id":2628},"_3-auto-memory让-cc-自己记笔记","3. Auto Memory：让 CC 自己记笔记",[15,2631,2632,2633,2636],{},"v2.1.59+ 引入的 auto memory 系统：CC 在会话中会自己判断\"这条信息以后还有用\"，写到 ",[79,2634,2635],{},"~\u002F.claude\u002Fprojects\u002F\u003Cproject>\u002Fmemory\u002F","。每次新会话自动加载前 200 行。",[488,2638,2639,2651],{},[491,2640,2641],{},[494,2642,2643,2645,2648],{},[497,2644],{},[497,2646,2647],{},"CLAUDE.md",[497,2649,2650],{},"Auto Memory",[504,2652,2653,2664,2674],{},[494,2654,2655,2658,2661],{},[509,2656,2657],{},"谁写",[509,2659,2660],{},"你",[509,2662,2663],{},"CC 自己",[494,2665,2666,2668,2671],{},[509,2667,2402],{},[509,2669,2670],{},"规范、铁律、架构",[509,2672,2673],{},"它发现的命令、纠正过的偏好",[494,2675,2676,2679,2682],{},[509,2677,2678],{},"角色",[509,2680,2681],{},"宪法",[509,2683,2684],{},"备忘录",[15,2686,2687,2690,2691,2693],{},[36,2688,2689],{},"实战建议","：把 auto memory 当成低优先级补充——铁律仍然必须进 CLAUDE.md。定期 ",[79,2692,2492],{}," review 自动生成的记忆、删除错误条目。",[15,2695,2696,2698,2699,2702],{},[36,2697,59],{}," Auto Memory 节省了\"手动记 build 命令是 ",[79,2700,2701],{},"pnpm dev:billing","\"这种琐事，但它不是强约束。不要让 auto memory 替代 CLAUDE.md 里的关键规范。",[22,2704,2706],{"id":2705},"_4-存量项目的-6-步-onboarding","4. 存量项目的 6 步 Onboarding",[15,2708,2709],{},"手里的老仓库 CC 完全不认识？按下面这套流程。",[410,2711,2713],{"id":2712},"step-1让-cc-做考古侦察","Step 1：让 CC 做\"考古侦察\"",[15,2715,2716],{},"进入 Plan 模式（只读），派给 Explore subagent：",[2718,2719,2720],"blockquote",{},[15,2721,2722],{},"\"你是新入职的资深工程师。生成一份项目考古报告：识别语言\u002F构建系统\u002F包管理器、目录结构及职责、内部包使用情况、历史沉淀（废弃代码\u002F风格断层）、测试策略分布、危险区域（循环依赖\u002F上帝文件\u002F热点文件）。不要修改任何代码，不确定处标 UNKNOWN。\"",[15,2724,2725,2726,2729],{},"仓库很大时，用 ",[79,2727,2728],{},"\u002Fbatch"," 派 5-10 个 Explore subagent 各盯一块，并行考古，主代理合并报告。子代理把脏活跑完只返回摘要，主会话上下文不爆。",[410,2731,2733],{"id":2732},"step-2根据侦察报告分层写-claudemd","Step 2：根据侦察报告分层写 CLAUDE.md",[15,2735,2736],{},"至少要有：项目级铁律 + 目录地图、关键子模块特有规则、遗留代码警告（\"这别重构，只加不改\"）。",[410,2738,2740],{"id":2739},"step-3给内部框架教教科书","Step 3：给内部框架\"教教科书\"",[15,2742,2743],{},"三种方式，按 ROI 从高到低：",[30,2745,2746,2755,2765],{},[33,2747,2748,2751,2752,2754],{},[36,2749,2750],{},"方式 A（强推）","：为每个内部框架写一个 Skill。主文件 ≤ 200 行，详细 API 放 ",[79,2753,1586],{},"。description 写清楚\"遇到 import '@company\u002Frpc' 时触发\"",[33,2756,2757,2760,2761,2764],{},[36,2758,2759],{},"方式 B","：框架文档同步到 ",[79,2762,2763],{},"docs\u002Fframeworks\u002F","，根 CLAUDE.md 只列索引",[33,2766,2767,2770],{},[36,2768,2769],{},"方式 C","：让 CC 从代码里自学归纳——\"扫描所有使用 @company\u002Frpc 的文件，归纳典型骨架和反模式，输出为 Skill 草稿。\"然后你人工 review",[410,2772,2774],{"id":2773},"step-4用学习示例锚定风格","Step 4：用\"学习示例\"锚定风格",[15,2776,2777],{},"在 CLAUDE.md 里写：",[72,2779,2781],{"className":1480,"code":2780,"language":1482,"meta":81,"style":81},"## 风格锚点\n- 好样本：`src\u002Fmodules\u002Forder\u002FOrderService.ts`\n- 好样本：`src\u002Fmodules\u002Finventory\u002F` 整个模块\n- 反样本（不要学）：`src\u002Fmodules\u002Flegacy-pricing\u002F`（历史遗留，即将废弃）\n",[79,2782,2783,2788,2793,2798],{"__ignoreMap":81},[203,2784,2785],{"class":205,"line":206},[203,2786,2787],{},"## 风格锚点\n",[203,2789,2790],{"class":205,"line":228},[203,2791,2792],{},"- 好样本：`src\u002Fmodules\u002Forder\u002FOrderService.ts`\n",[203,2794,2795],{"class":205,"line":250},[203,2796,2797],{},"- 好样本：`src\u002Fmodules\u002Finventory\u002F` 整个模块\n",[203,2799,2800],{"class":205,"line":279},[203,2801,2802],{},"- 反样本（不要学）：`src\u002Fmodules\u002Flegacy-pricing\u002F`（历史遗留，即将废弃）\n",[15,2804,2805,2808],{},[36,2806,2807],{},"这比写 100 条风格规则都有效","——代码里已经把所有隐含规范固化了，CC 模仿能力极强。",[410,2810,2812],{"id":2811},"step-5为方法论写硬约束","Step 5：为方法论写硬约束",[15,2814,2815],{},"DDD 铁律示例：",[72,2817,2819],{"className":1480,"code":2818,"language":1482,"meta":81,"style":81},"## DDD 约束\n- 领域层不得 import 任何 infrastructure\u002Finterfaces 代码\n- Entity 只能通过 Repository 持久化，禁止应用层直接拼 SQL\n- 业务不变量用 ValueObject 或 Entity 方法表达，禁止在 Service 里散落校验\n",[79,2820,2821,2826,2831,2836],{"__ignoreMap":81},[203,2822,2823],{"class":205,"line":206},[203,2824,2825],{},"## DDD 约束\n",[203,2827,2828],{"class":205,"line":228},[203,2829,2830],{},"- 领域层不得 import 任何 infrastructure\u002Finterfaces 代码\n",[203,2832,2833],{"class":205,"line":250},[203,2834,2835],{},"- Entity 只能通过 Repository 持久化，禁止应用层直接拼 SQL\n",[203,2837,2838],{"class":205,"line":279},[203,2839,2840],{},"- 业务不变量用 ValueObject 或 Entity 方法表达，禁止在 Service 里散落校验\n",[15,2842,2843,2846],{},[36,2844,2845],{},"铁律用\"禁止\u002F必须\"句式，不要用\"建议\u002F尽量\"","——Agent 对硬约束执行力更强。",[410,2848,2850],{"id":2849},"step-6首轮小任务校准","Step 6：首轮小任务校准",[15,2852,2853],{},"不要直接让 CC 上手做大需求。挑一个简单 bug 走 plan 模式，你对它的产出做严格 diff review，不符合团队风格的 → 反馈进 CLAUDE.md 或对应 Skill。再让它做第二个，迭代到产出基本符合预期。走 1-2 天，后面几个月都受益。",[15,2855,2856,2858],{},[36,2857,59],{}," 新项目落地难的不是\"配 CLAUDE.md\"，而是把你脑子里的隐性工程判断显式化。这套 6 步流程的精髓是：先考古、再分层、用示例锚定风格、小任务迭代校准——而不是一口气写完然后指望它完美。",[22,2860,2862],{"id":2861},"_5-大仓定位代码的日更-sop","5. 大仓定位代码的日更 SOP",[410,2864,2866],{"id":2865},"需求型我要做-x-功能涉及哪些模块","需求型：\"我要做 X 功能，涉及哪些模块？\"",[72,2868,2871],{"className":2869,"code":2870,"language":77},[75],"1. \u002Fclear\n2. @CLAUDE.md（明确涉及哪个子系统也 @ 对应 CLAUDE.md）\n3. \"进入 plan 模式。ultrathink。不要改代码。\n   调 code-explorer 去做调研，只把清单返回。\n   产出：业务流程(3-8步) \u002F 每步涉及的文件:行号 \u002F 需新增的文件 \u002F\n         需修改的文件 \u002F 风险点 \u002F 测试计划 \u002F 建议的 PR 拆分\"\n",[79,2872,2870],{"__ignoreMap":81},[410,2874,2876],{"id":2875},"bug-型这个错误在哪触发的","Bug 型：\"这个错误在哪触发的？\"",[72,2878,2881],{"className":2879,"code":2880,"language":77},[75],"1. \u002Fclear + 贴完整错误信息\n2. \"ultrathink。先不要改代码。\n   a) 从 stack trace 定位最上面的业务代码帧\n   b) 提出 3 个最可能的根因假设，每个给出证据、反证、最小验证方法\n   c) 排序给出优先验证顺序\n   等我选一个再继续。\"\n",[79,2882,2880],{"__ignoreMap":81},[15,2884,2885,2888],{},[36,2886,2887],{},"关键：两段式（先假设 → 再验证）比直接让它修 bug 效果好得多。"," 把你自己查 bug 的思维过程显式化给 CC。",[15,2890,2891,2893],{},[36,2892,59],{}," 大仓导航的核心原则是\"让 CC 在需要的时候看到需要的那部分\"。Explorer subagent 做脏活 + plan 模式防冲动 + 结构化产出便于 review——这是反复验证过的高效组合。",[22,2895,2897],{"id":2896},"_6-一个从零让-cc-符合团队要求的-checklist","6. 一个\"从零让 CC 符合团队要求\"的 Checklist",[30,2899,2902,2911,2921,2930,2938,2947,2957,2963,2969,2975],{"className":2900},[2901],"contains-task-list",[33,2903,2906,2910],{"className":2904},[2905],"task-list-item",[2907,2908],"input",{"disabled":702,"type":2909},"checkbox"," 根目录 CLAUDE.md：项目速览 + 铁律 + 目录地图 + 风格锚点 + Skills 索引",[33,2912,2914,2916,2917,2920],{"className":2913},[2905],[2907,2915],{"disabled":702,"type":2909}," 关键子模块 ",[79,2918,2919],{},"*\u002FCLAUDE.md","：模块特有规则、踩坑记录",[33,2922,2924,2926,2927,2929],{"className":2923},[2905],[2907,2925],{"disabled":702,"type":2909}," ",[79,2928,2226],{}," 至少 3 个：内部框架 × N + 团队方法论",[33,2931,2933,2926,2935,2937],{"className":2932},[2905],[2907,2934],{"disabled":702,"type":2909},[79,2936,2763],{}," 同步内部框架文档（或让 CC 从代码归纳）",[33,2939,2941,2926,2943,2946],{"className":2940},[2905],[2907,2942],{"disabled":702,"type":2909},[79,2944,2945],{},".claude\u002Fsettings.json"," 配好 PostToolUse typecheck\u002Flint hook",[33,2948,2950,2952,2953,2956],{"className":2949},[2905],[2907,2951],{"disabled":702,"type":2909}," 配好 ",[79,2954,2955],{},"\u002Fpermissions","：限制危险 bash、限定工作区",[33,2958,2960,2962],{"className":2959},[2905],[2907,2961],{"disabled":702,"type":2909}," 接入 1-2 个 MCP（至少 Git 托管 + 任务系统）",[33,2964,2966,2968],{"className":2965},[2905],[2907,2967],{"disabled":702,"type":2909}," 选 2-3 个\"好样本文件\u002F模块\"写进风格锚点",[33,2970,2972,2974],{"className":2971},[2905],[2907,2973],{"disabled":702,"type":2909}," 走一次小任务校准，把发现的偏差回写到 CLAUDE.md",[33,2976,2978,2980],{"className":2977},[2905],[2907,2979],{"disabled":702,"type":2909}," 提交到 git 并让团队成员也 pull 一份",[22,2982,648],{"id":648},[15,2984,2985],{},"让 CC 真正理解你的代码库，本质上是三件事的层层推进：",[115,2987,2988,2994,3003],{},[33,2989,2990,2993],{},[36,2991,2992],{},"编码隐性知识","：把团队规范、内部框架用法、历史遗留约束从人脑搬到 CLAUDE.md 和 Skills",[33,2995,2996,2999,3000,3002],{},[36,2997,2998],{},"精准上下文管理","：分层 CLAUDE.md + ",[79,3001,2514],{}," + auto memory 三层互补，确保 CC 在该看到的时候看到该看的",[33,3004,3005,3008],{},[36,3006,3007],{},"迭代校准","：别指望一次写对。小任务跑起来，发现偏差就回写，两周下来准确度会有质的飞跃",[15,3010,3011],{},"这套体系一旦搭好，新同事 clone 仓库后开 CC 就能直接干活——架构约束、代码风格、踩坑记录全部内化在工具链里。这才是 AI 时代的团队知识管理。",[15,3013,3014],{},[671,3015,674],{"href":673},[676,3017,3018],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":81,"searchDepth":228,"depth":228,"links":3020},[3021,3025,3027,3028,3036,3040,3041],{"id":2357,"depth":228,"text":2358,"children":3022},[3023,3024],{"id":2387,"depth":250,"text":2387},{"id":2465,"depth":250,"text":2465},{"id":2510,"depth":228,"text":3026},"2. .claude\u002Frules\u002F：另一种切分维度",{"id":2628,"depth":228,"text":2629},{"id":2705,"depth":228,"text":2706,"children":3029},[3030,3031,3032,3033,3034,3035],{"id":2712,"depth":250,"text":2713},{"id":2732,"depth":250,"text":2733},{"id":2739,"depth":250,"text":2740},{"id":2773,"depth":250,"text":2774},{"id":2811,"depth":250,"text":2812},{"id":2849,"depth":250,"text":2850},{"id":2861,"depth":228,"text":2862,"children":3037},[3038,3039],{"id":2865,"depth":250,"text":2866},{"id":2875,"depth":250,"text":2876},{"id":2896,"depth":228,"text":2897},{"id":648,"depth":228,"text":648},"Claude Code 最大的优势是它有工具、能改代码。但它最大的盲区也很明显：它不认识你们公司的内部框架，不知道你们团队三年沉淀下来的\"不写进文档的约定\"，更不懂那个 2000 行的 legacy-pricing.ts 为什么碰不得。",{},"\u002Fblog\u002Fclaude-code-team-adoption",{"title":2336,"description":3042},"blog\u002Fclaude-code-team-adoption",[2328,2647,3048,3049,2332],"团队协作","代码库管理","5rt9paHjy1Wh5ZkO18-k2PMmxGChn5ShAT0nyFoy4qw",1779959652732]