<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; harness engineering</title>
	<atom:link href="https://www.phppan.com/tag/harness-engineering/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 16 Aug 2026 05:16:50 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>从 Pi 到 DSH：Agent Harness 如何从「可扩展」走向「自生长」</title>
		<link>https://www.phppan.com/2026/08/from-pi-to-dsh-how-agent-harness-evolves-from-scalable-to-self-growing/</link>
		<comments>https://www.phppan.com/2026/08/from-pi-to-dsh-how-agent-harness-evolves-from-scalable-to-self-growing/#comments</comments>
		<pubDate>Sun, 16 Aug 2026 05:16:50 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[DSH]]></category>
		<category><![CDATA[harness engineering]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2528</guid>
		<description><![CDATA[大模型能力持续提升之后，Agent 系统的竞争焦点正在发生变化。 过去，我们主要关心模型能不能理解任务、调用工 [&#8230;]]]></description>
				<content:encoded><![CDATA[<section id="nice" style="color: #000000;" data-tool="mdnice编辑器" data-website="https://www.mdnice.com">
<p data-tool="mdnice编辑器">大模型能力持续提升之后，Agent 系统的竞争焦点正在发生变化。</p>
<p data-tool="mdnice编辑器">过去，我们主要关心模型能不能理解任务、调用工具、编写代码。现在，更重要的问题逐渐变成：<strong>模型之外的系统，能否为 Agent 提供一个可以持续变化的运行环境？</strong></p>
<p data-tool="mdnice编辑器">这个运行环境通常被称为 <strong>Agent Harness</strong>。</p>
<p data-tool="mdnice编辑器">Harness 负责把模型、提示词、工具、记忆、上下文、权限和外部环境连接起来。它决定模型能够看到什么、调用什么、保存什么，以及一次行动会产生怎样的系统影响。</p>
<p data-tool="mdnice编辑器">从这个角度看，Agent 的能力并不只来自模型，用一个公式来表达，大概如下：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Agent 能力
=
模型能力
× 上下文组织
× 工具系统
× 运行时结构
× 生命周期治理
</code></pre>
<p data-tool="mdnice编辑器">如果 Harness 是固定的，那么即使模型越来越强，Agent 的能力边界仍然主要由开发者预先决定。</p>
<p data-tool="mdnice编辑器">如果 Harness 可以扩展，用户和开发者就能不断为 Agent 增加工具、技能和工作流。</p>
<p data-tool="mdnice编辑器">但如果我们希望 Agent 进一步具备「自生长」能力，仅仅提供扩展接口还不够。系统还必须允许 Agent：</p>
<ol data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">发现自己的能力缺口；</section>
</li>
<li>
<section style="color: #010101;">生成或引入候选能力；</section>
</li>
<li>
<section style="color: #010101;">在运行时安全地激活这些能力；</section>
</li>
<li>
<section style="color: #010101;">验证变化是否有效；</section>
</li>
<li>
<section style="color: #010101;">在失败时完整回滚；</section>
</li>
<li>
<section style="color: #010101;">将成功经验沉淀为可复用组件；</section>
</li>
<li>
<section style="color: #010101;">淘汰已经失效或长期无用的能力。</section>
</li>
</ol>
<p data-tool="mdnice编辑器">Pi 与 DSH 可以被视为这条演进路径上的两个阶段。</p>
<p data-tool="mdnice编辑器">Pi 回答的是：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如何构建一个足够小、足够开放，可以持续扩展的 Agent Harness？</p></blockquote>
<p data-tool="mdnice编辑器">DSH 进一步追问：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如何让 Agent 不只是使用外部提供的扩展，而是安全地参与自身能力结构的形成？</p></blockquote>
<p data-tool="mdnice编辑器">这不是从一种插件格式切换到另一种插件格式，而是 Agent Harness 从<strong>开放扩展平台</strong>向<strong>能力生长环境</strong>的转变。</p>
<h1 data-tool="mdnice编辑器"><span class="content">1. 什么是 Agent Harness</span></h1>
<p data-tool="mdnice编辑器">一个最简单的 Agent，可以被表示为：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Model
  ↓
Prompt
  ↓
Tool Call
  ↓
Environment
</code></pre>
<p data-tool="mdnice编辑器">模型接收上下文，生成工具调用，再根据工具结果继续推理。</p>
<p data-tool="mdnice编辑器">但在真实系统里，Agent 还需要处理更多问题：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">当前有哪些工具可用？</section>
</li>
<li>
<section style="color: #010101;">工具由谁注册？</section>
</li>
<li>
<section style="color: #010101;">不同任务应该使用什么模型？</section>
</li>
<li>
<section style="color: #010101;">哪些信息应该进入上下文？</section>
</li>
<li>
<section style="color: #010101;">哪些记忆需要跨会话保存？</section>
</li>
<li>
<section style="color: #010101;">如何限制文件、网络和进程权限？</section>
</li>
<li>
<section style="color: #010101;">工具调用失败后如何恢复？</section>
</li>
<li>
<section style="color: #010101;">新能力如何加载？</section>
</li>
<li>
<section style="color: #010101;">组件移除后如何清理副作用？</section>
</li>
<li>
<section style="color: #010101;">不同组件之间的依赖如何表达？</section>
</li>
</ul>
<p data-tool="mdnice编辑器">于是，Agent 的实际结构更接近于：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">                ┌─────────────┐
                │    Model    │
                └──────┬──────┘
                       │
                ┌──────▼──────┐
                │ Agent Loop  │
                └──────┬──────┘
                       │
       ┌───────────────┼────────────────┐
       │               │                │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│    Tools    │ │    Memory   │ │   Context   │
└─────────────┘ └─────────────┘ └─────────────┘
       │               │                │
       └───────────────┼────────────────┘
                       │
                ┌──────▼──────┐
                │ Environment │
                └─────────────┘
</code></pre>
<p data-tool="mdnice编辑器">Harness 并不是模型外面的一层简单包装。</p>
<p data-tool="mdnice编辑器">它实际上规定了 Agent 的：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">能力边界；</section>
</li>
<li>
<section style="color: #010101;">行为边界；</section>
</li>
<li>
<section style="color: #010101;">状态边界；</section>
</li>
<li>
<section style="color: #010101;">权限边界；</section>
</li>
<li>
<section style="color: #010101;">演化边界。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，当我们讨论 Agent 是否可以扩展、重构甚至自生长时，本质上讨论的不是模型参数如何变化，而是 <strong>Harness 能否安全地改变自身结构</strong>。</p>
<h1 data-tool="mdnice编辑器"><span class="content">2. Pi：以最小内核换取最大扩展空间</span></h1>
<p data-tool="mdnice编辑器">Pi 的核心思想非常明确：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>不要预先替用户决定完整工作流，而是提供足够小的基础能力，让用户自己构建需要的 Harness。</p></blockquote>
<p data-tool="mdnice编辑器">Pi 将自己定义为一个最小化的 Agent Harness，并通过 Extensions、Skills、Prompt Templates、Themes 和 Packages 提供扩展能力。它允许用户修改工具、命令、模型提供商、工作流、上下文处理和终端界面，也支持将这些资源打包后通过 npm 或 Git 分发。(<a style="font-weight: bold; color: #ef7060;" href="https://pi.dev/?via=topaitools">pi.dev</a>)</p>
<p data-tool="mdnice编辑器">这背后是一种「原语优先」的设计哲学：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">不是：
内置所有功能

而是：
提供少量原语
+
开放扩展接口
+
允许用户自行组合
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">2.1 最小化不是能力不足</span></h2>
<p data-tool="mdnice编辑器">传统 Agent 产品通常倾向于内置更多功能：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">规划模式；</section>
</li>
<li>
<section style="color: #010101;">子 Agent；</section>
</li>
<li>
<section style="color: #010101;">权限确认；</section>
</li>
<li>
<section style="color: #010101;">MCP 集成；</section>
</li>
<li>
<section style="color: #010101;">后台任务；</section>
</li>
<li>
<section style="color: #010101;">长期记忆；</section>
</li>
<li>
<section style="color: #010101;">沙箱；</section>
</li>
<li>
<section style="color: #010101;">Todo 系统。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Pi 选择了另一条路线：这些能力不一定需要成为内核的一部分，它们可以通过扩展或外部环境实现。</p>
<p data-tool="mdnice编辑器">Pi 当前提供文件读取、文件修改、内容搜索和命令执行等内置工具，同时允许通过命令行配置工具集合，也允许 Extension 注册新的工具或覆盖现有工具。(<a style="font-weight: bold; color: #ef7060;" href="https://pi.dev/docs/latest/usage?utm_source=openai">pi.dev</a>)</p>
<p data-tool="mdnice编辑器">这种设计的意义把稳定的内核和变化的能力分开：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">稳定部分：
模型调用、Agent Loop、会话、基础工具、扩展 API

变化部分：
工具、技能、上下文、工作流、权限策略、界面、模型路由
</code></pre>
<p data-tool="mdnice编辑器">只要扩展接口足够开放，功能就不必全部固化在核心代码中。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">2.2 Pi 的四类扩展资源</span></h2>
<p data-tool="mdnice编辑器">从 Harness 的角度看，Pi 的可扩展性主要体现在以下几个层面。</p>
<h3 data-tool="mdnice编辑器"><span class="content">2.2.1 Extensions：改变运行时行为</span></h3>
<p data-tool="mdnice编辑器">Extension 是可以进入 Agent 运行时的代码模块。</p>
<p data-tool="mdnice编辑器">它可以：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">注册工具和命令；</section>
</li>
<li>
<section style="color: #010101;">监听工具调用；</section>
</li>
<li>
<section style="color: #010101;">拦截或修改行为；</section>
</li>
<li>
<section style="color: #010101;">改变上下文；</section>
</li>
<li>
<section style="color: #010101;">切换模型；</section>
</li>
<li>
<section style="color: #010101;">增加权限检查；</section>
</li>
<li>
<section style="color: #010101;">实现自定义 UI；</section>
</li>
<li>
<section style="color: #010101;">覆盖内置工具；</section>
</li>
<li>
<section style="color: #010101;">连接外部系统。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，Extension 改变的不只是模型“知道什么”，还可以直接改变 Harness“如何运行”。</p>
<h3 data-tool="mdnice编辑器"><span class="content">2.2.2 Skills：注入按需能力</span></h3>
<p data-tool="mdnice编辑器">Skill 更接近一种可复用的过程知识。</p>
<p data-tool="mdnice编辑器">它可以告诉 Agent：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">在什么情况下使用某种方法；</section>
</li>
<li>
<section style="color: #010101;">如何执行特定工作流；</section>
</li>
<li>
<section style="color: #010101;">如何调用外部命令；</section>
</li>
<li>
<section style="color: #010101;">如何处理某类项目；</section>
</li>
<li>
<section style="color: #010101;">如何检查输出质量。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Pi 将 Skill 设计为按需加载的能力包，使 Agent 不必在每次会话开始时把所有知识都放进上下文。(<a style="font-weight: bold; color: #ef7060;" href="https://pi.dev/?via=topaitools">pi.dev</a>)</p>
<h3 data-tool="mdnice编辑器"><span class="content">2.2.3 Prompt Templates：固化交互模式</span></h3>
<p data-tool="mdnice编辑器">Prompt Template 将常见任务封装成可复用提示词，例如：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">代码审查；</section>
</li>
<li>
<section style="color: #010101;">架构分析；</section>
</li>
<li>
<section style="color: #010101;">发布检查；</section>
</li>
<li>
<section style="color: #010101;">测试生成；</section>
</li>
<li>
<section style="color: #010101;">故障排查。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">它改变的是任务入口和交互结构。</p>
<h3 data-tool="mdnice编辑器"><span class="content">2.2.4 Packages：分发完整能力</span></h3>
<p data-tool="mdnice编辑器">Package 可以将 Extensions、Skills、Prompt Templates 和 Themes 组合起来，通过 npm、Git 或本地路径安装。Pi 还支持临时加载 Package，使组件只对当前运行生效。(<a style="font-weight: bold; color: #ef7060;" href="https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/packages.md">github.com</a>)</p>
<p data-tool="mdnice编辑器">这使 Pi 不只是一个 Agent，也成为一个 Harness 能力分发平台：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Pi Package
├── Extensions
├── Skills
├── Prompts
└── Themes
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">2.3 Pi 的关键突破：Agent 可以参与修改 Harness</span></h2>
<p data-tool="mdnice编辑器">Pi 最值得关注的地方，不只是「插件多」。</p>
<p data-tool="mdnice编辑器">它的官方描述明确鼓励用户让 Pi 编写自己需要的扩展，并在修改后通过重新加载继续当前工作。(<a style="font-weight: bold; color: #ef7060;" href="https://pi.dev/?via=topaitools">pi.dev</a>)</p>
<p data-tool="mdnice编辑器">这意味着一种新的工作方式正在出现：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Agent 发现缺少某项能力
        ↓
Agent 编写 Extension
        ↓
用户检查或确认
        ↓
重新加载 Harness
        ↓
Agent 使用新增能力继续任务
</code></pre>
<p data-tool="mdnice编辑器">过去，Agent 与开发工具之间的关系通常是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">人类开发 Harness
Agent 使用 Harness
</code></pre>
<p data-tool="mdnice编辑器">在 Pi 中，它开始变成：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">人类定义目标
Agent 修改 Harness
Agent 使用修改后的 Harness
</code></pre>
<p data-tool="mdnice编辑器">这是从「可扩展」走向「自生长」的重要一步。</p>
<p data-tool="mdnice编辑器">但是，这还不等于完整的自生长。</p>
<h1 data-tool="mdnice编辑器"><span class="content">3. 行为自治不等于结构自治</span></h1>
<p data-tool="mdnice编辑器">理解 Pi 与 DSH 的关系，需要区分两种不同的自治。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">3.1 行为自治</span></h2>
<p data-tool="mdnice编辑器">行为自治指 Agent 可以在已有能力范围内自主决定：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">下一步做什么；</section>
</li>
<li>
<section style="color: #010101;">调用哪个工具；</section>
</li>
<li>
<section style="color: #010101;">如何拆解任务；</section>
</li>
<li>
<section style="color: #010101;">是否修改文件；</section>
</li>
<li>
<section style="color: #010101;">是否运行测试；</section>
</li>
<li>
<section style="color: #010101;">如何根据结果调整计划。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">此时，Agent 的选择空间是动态的，但能力集合通常是预先确定的。</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">固定工具集合
    ↓
Agent 自主选择工具
    ↓
完成任务
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">3.2 结构自治</span></h2>
<p data-tool="mdnice编辑器">结构自治指 Agent 可以改变自己的能力结构：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">创建新工具；</section>
</li>
<li>
<section style="color: #010101;">安装新组件；</section>
</li>
<li>
<section style="color: #010101;">替换 Memory；</section>
</li>
<li>
<section style="color: #010101;">修改上下文策略；</section>
</li>
<li>
<section style="color: #010101;">调整模型 Router；</section>
</li>
<li>
<section style="color: #010101;">增加权限规则；</section>
</li>
<li>
<section style="color: #010101;">组合新的执行流程；</section>
</li>
<li>
<section style="color: #010101;">卸载无效组件。</section>
</li>
</ul>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">当前能力结构
    ↓
Agent 发现能力缺口
    ↓
生成候选组件
    ↓
改变 Harness
    ↓
形成新的能力结构
</code></pre>
<p data-tool="mdnice编辑器">Pi 已经为结构自治打开了入口。</p>
<p data-tool="mdnice编辑器">但它的扩展机制主要回答的是：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如何把一项新能力加入系统？</p></blockquote>
<p data-tool="mdnice编辑器">真正的自生长还必须回答：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">新能力应该在什么条件下激活？</section>
</li>
<li>
<section style="color: #010101;">它依赖哪些已有能力？</section>
</li>
<li>
<section style="color: #010101;">它失败后能否完整退出？</section>
</li>
<li>
<section style="color: #010101;">它注册的工具和监听器由谁撤销？</section>
</li>
<li>
<section style="color: #010101;">如何判断变化带来了正收益？</section>
</li>
<li>
<section style="color: #010101;">如何防止不同扩展相互冲突？</section>
</li>
<li>
<section style="color: #010101;">如何把一次临时变化沉淀成长期能力？</section>
</li>
<li>
<section style="color: #010101;">如何淘汰不再适用的组件？</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这些问题将我们从扩展系统带到了组件运行时。</p>
<h1 data-tool="mdnice编辑器"><span class="content">4. DSH：为 Harness 自生长建立运行时基础</span></h1>
<p data-tool="mdnice编辑器">本文讨论的 DSH，不只是另一个插件系统。</p>
<p data-tool="mdnice编辑器">它试图将 Agent Harness 表达为一个可以在运行中不断组合和重组的组件系统。</p>
<p data-tool="mdnice编辑器">其基本结构可以概括为：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Component
=
Context
+
Effect
+
Cleanup
+
Coeffects
</code></pre>
<p data-tool="mdnice编辑器">这四个概念分别回答四个问题：</p>
<section class="table-container" data-tool="mdnice编辑器">
<table>
<thead>
<tr>
<th style="color: #000000;">概念</th>
<th style="color: #000000;">回答的问题</th>
</tr>
</thead>
<tbody>
<tr style="color: #000000;">
<td>Context</td>
<td>组件可以看到和使用什么？</td>
</tr>
<tr style="color: #000000;">
<td>Effect</td>
<td>组件加入系统后会产生什么影响？</td>
</tr>
<tr style="color: #000000;">
<td>Cleanup</td>
<td>组件退出时如何撤销影响？</td>
</tr>
<tr style="color: #000000;">
<td>Coeffects</td>
<td>组件依赖哪些外部能力或其他组件？</td>
</tr>
</tbody>
</table>
</section>
<p data-tool="mdnice编辑器">DSH 的目标不是让所有模块都能任意修改系统，而是让变化成为一种<strong>显式、可追踪、可逆的运行时操作</strong>。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.1 Context：为能力提供明确边界</span></h2>
<p data-tool="mdnice编辑器">一个组件不能直接访问所有系统状态。</p>
<p data-tool="mdnice编辑器">它应该通过 Context 获取所需能力，例如：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Context
├── Model Registry
├── Tool Registry
├── Memory
├── Event Bus
├── Session
├── Logger
├── Storage
├── Permission
└── Environment
</code></pre>
<p data-tool="mdnice编辑器">Context 的第一层作用是解耦。</p>
<p data-tool="mdnice编辑器">组件不需要知道某个能力的具体实现，只需要知道运行环境向它提供了什么。</p>
<p data-tool="mdnice编辑器">例如，一个模型路由组件可能只依赖：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Model Registry
Task Metadata
Usage Metrics
</code></pre>
<p data-tool="mdnice编辑器">一个长期记忆组件可能只依赖：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Session Events
Embedding Service
Storage
Context Injector
</code></pre>
<p data-tool="mdnice编辑器">一个工具组件则可能只依赖：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Tool Registry
Credentials
Network
Logger
</code></pre>
<p data-tool="mdnice编辑器">Context 的第二层作用是限制能力边界。</p>
<p data-tool="mdnice编辑器">如果组件只能通过 Context 访问环境，那么系统就可以决定：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">哪些资源向它开放；</section>
</li>
<li>
<section style="color: #010101;">哪些能力只读；</section>
</li>
<li>
<section style="color: #010101;">哪些调用需要权限；</section>
</li>
<li>
<section style="color: #010101;">哪些状态不能跨组件共享；</section>
</li>
<li>
<section style="color: #010101;">哪些操作只能在 Sandbox 中执行。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，Context 不只是依赖注入，也是一种能力安全模型：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">组件能做什么
≈
Context 向它暴露什么
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.2 Effect 与 Cleanup：让变化可以被撤销</span></h2>
<p data-tool="mdnice编辑器">当组件加入 Harness 时，通常会产生副作用。</p>
<p data-tool="mdnice编辑器">例如：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">注册一个工具；</section>
</li>
<li>
<section style="color: #010101;">添加一个事件监听器；</section>
</li>
<li>
<section style="color: #010101;">打开数据库连接；</section>
</li>
<li>
<section style="color: #010101;">启动后台任务；</section>
</li>
<li>
<section style="color: #010101;">修改模型路由；</section>
</li>
<li>
<section style="color: #010101;">向上下文注入内容；</section>
</li>
<li>
<section style="color: #010101;">挂载文件目录；</section>
</li>
<li>
<section style="color: #010101;">注册快捷键；</section>
</li>
<li>
<section style="color: #010101;">创建缓存；</section>
</li>
<li>
<section style="color: #010101;">改变权限策略。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这些变化可以统一理解为 Effect：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Component
    ↓
Effect
    ↓
Harness 状态发生变化
</code></pre>
<p data-tool="mdnice编辑器">问题在于，大多数插件系统只强调如何创建 Effect，却没有把撤销 Effect 当作同等重要的能力。</p>
<p data-tool="mdnice编辑器">于是，组件卸载后可能出现：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">工具仍然留在 Registry 中；</section>
</li>
<li>
<section style="color: #010101;">事件监听器重复注册；</section>
</li>
<li>
<section style="color: #010101;">后台任务继续运行；</section>
</li>
<li>
<section style="color: #010101;">网络连接没有关闭；</section>
</li>
<li>
<section style="color: #010101;">临时文件没有删除；</section>
</li>
<li>
<section style="color: #010101;">Context 中残留失效状态；</section>
</li>
<li>
<section style="color: #010101;">新旧路由规则同时生效。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">在 DSH 中，Effect 应该返回对应的 Cleanup：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Effect(Context) → Cleanup
</code></pre>
<p data-tool="mdnice编辑器">例如：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-function"><span class="hljs-keyword" style="color: #c678dd;">function</span> <span class="hljs-title" style="color: #61aeee;">activate</span>(<span class="hljs-params">context</span>) </span>{
  <span class="hljs-keyword" style="color: #c678dd;">const</span> unregister = context.tools.register(myTool)

  <span class="hljs-keyword" style="color: #c678dd;">return</span> <span class="hljs-function"><span class="hljs-keyword" style="color: #c678dd;">function</span> <span class="hljs-title" style="color: #61aeee;">cleanup</span>() </span>{
    unregister()
  }
}
</code></pre>
<p data-tool="mdnice编辑器">更复杂的组件可能产生多个副作用：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-function"><span class="hljs-keyword" style="color: #c678dd;">function</span> <span class="hljs-title" style="color: #61aeee;">activate</span>(<span class="hljs-params">context</span>) </span>{
  <span class="hljs-keyword" style="color: #c678dd;">const</span> stopTool = registerTool(context)
  <span class="hljs-keyword" style="color: #c678dd;">const</span> stopListener = registerListener(context)
  <span class="hljs-keyword" style="color: #c678dd;">const</span> stopWorker = startWorker(context)
  <span class="hljs-keyword" style="color: #c678dd;">const</span> closeConnection = connectDatabase(context)

  <span class="hljs-keyword" style="color: #c678dd;">return</span> <span class="hljs-keyword" style="color: #c678dd;">async</span> <span class="hljs-function"><span class="hljs-keyword" style="color: #c678dd;">function</span> <span class="hljs-title" style="color: #61aeee;">cleanup</span>() </span>{
    <span class="hljs-keyword" style="color: #c678dd;">await</span> stopWorker()
    stopListener()
    stopTool()
    <span class="hljs-keyword" style="color: #c678dd;">await</span> closeConnection()
  }
}
</code></pre>
<p data-tool="mdnice编辑器">这使组件具备完整生命周期：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">创建
  ↓
激活
  ↓
运行
  ↓
停用
  ↓
清理
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.3 时间可组合性：让 Agent 有资格试错</span></h2>
<p data-tool="mdnice编辑器">Effect 与 Cleanup 提供的是一种<strong>时间可组合性</strong>。</p>
<p data-tool="mdnice编辑器">一个组件可以在某个时刻进入系统，也可以在另一个时刻完整退出：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">t₀：Harness 原始状态

t₁：组件进入
    → 注册工具
    → 启动服务
    → 注入上下文

t₂：组件运行

t₃：组件退出
    → 移除工具
    → 停止服务
    → 撤销上下文

t₄：Harness 恢复到可预测状态
</code></pre>
<p data-tool="mdnice编辑器">这对普通插件系统很重要，但对自生长系统更重要。</p>
<p data-tool="mdnice编辑器">因为自生长必然包含试错。</p>
<p data-tool="mdnice编辑器">Agent 创建的新工具、新路由器、新记忆策略，不可能每次都正确。如果一次失败的尝试不能被完整撤销，那么每次实验都会向系统中留下残余状态。</p>
<p data-tool="mdnice编辑器">最终，所谓“生长”就会退化成不可控的复杂度积累。</p>
<p data-tool="mdnice编辑器">因此，自生长的基本过程不应该是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">生成组件
  ↓
永久安装
</code></pre>
<p data-tool="mdnice编辑器">而应该是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">生成候选组件
      ↓
执行受控 Effect
      ↓
验证运行结果
   ┌──┴──┐
 成功    失败
  │       │
保留   Cleanup
</code></pre>
<p data-tool="mdnice编辑器">Cleanup 的意义不只是“支持热卸载”。</p>
<p data-tool="mdnice编辑器">它赋予 Agent 一种更关键的能力：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>在不永久污染系统的前提下试验新的自身结构。</p></blockquote>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.4 Coeffects：让依赖关系成为运行时的一部分</span></h2>
<p data-tool="mdnice编辑器">时间可组合性解决的是组件何时进入、何时退出。</p>
<p data-tool="mdnice编辑器">但 Agent Harness 的组件并不是彼此孤立的。</p>
<p data-tool="mdnice编辑器">如果依赖关系只是组件内部的隐式假设，运行时就无法回答：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">组件现在能否启动？</section>
</li>
<li>
<section style="color: #010101;">它缺少什么能力？</section>
</li>
<li>
<section style="color: #010101;">某个依赖消失后，哪些组件应该停用？</section>
</li>
<li>
<section style="color: #010101;">替换一个 Provider 会影响哪些组件？</section>
</li>
<li>
<section style="color: #010101;">哪些组件可以被安全卸载？</section>
</li>
<li>
<section style="color: #010101;">一个候选组件是否与当前环境兼容？</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Coeffects 用于显式表达组件所需的外部条件：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Effect：
组件对系统做什么

Coeffects：
组件需要系统提供什么
</code></pre>
<p data-tool="mdnice编辑器">例如：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-keyword" style="color: #c678dd;">const</span> vectorMemory = {
  coeffects: [
    <span class="hljs-string" style="color: #98c379;">"embedding-model"</span>,
    <span class="hljs-string" style="color: #98c379;">"vector-storage"</span>,
    <span class="hljs-string" style="color: #98c379;">"session-events"</span>
  ],

  effect(context) {
    <span class="hljs-comment" style="font-style: italic; color: #5c6370;">// 激活 Memory</span>
    <span class="hljs-keyword" style="color: #c678dd;">return</span> cleanup
  }
}
</code></pre>
<p data-tool="mdnice编辑器">运行时可以根据当前 Context 判断组件是否具备激活条件：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">依赖全部满足
    ↓
组件激活

依赖不完整
    ↓
组件保持未激活

依赖运行中消失
    ↓
执行 Cleanup
</code></pre>
<p data-tool="mdnice编辑器">这使 Harness 不再只是一个插件列表，而是一个动态依赖图：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Credential
    ↓
GitHub Provider
    ↓
GitHub Tool
    ↓
Repository Agent
</code></pre>
<p data-tool="mdnice编辑器">或者：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Embedding Model ─┐
                 ├→ Vector Memory → Context Injector
Vector Storage ──┘
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.5 空间可组合性：让生长不是无序堆积</span></h2>
<p data-tool="mdnice编辑器">Coeffects 提供的是一种<strong>空间可组合性</strong>。</p>
<p data-tool="mdnice编辑器">组件不是按照固定顺序硬编码在系统中，而是根据能力和依赖形成运行时拓扑。</p>
<p data-tool="mdnice编辑器">当一个能力出现时，依赖它的组件可以被激活；当这个能力消失时，相关组件可以被停用：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Sandbox 出现
    ↓
Code Executor 激活
    ↓
Test Runner 激活
    ↓
Coding Agent 获得安全执行能力
</code></pre>
<p data-tool="mdnice编辑器">如果 Sandbox 被移除：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Sandbox 消失
    ↓
Code Executor Cleanup
    ↓
Test Runner Cleanup
    ↓
相关工具从 Agent 能力集合中撤销
</code></pre>
<p data-tool="mdnice编辑器">这与传统插件系统有一个关键区别。</p>
<p data-tool="mdnice编辑器">传统插件系统更像：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">安装了什么
=
系统拥有什么
</code></pre>
<p data-tool="mdnice编辑器">而动态组件运行时更像：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">当前可用能力
=
当前组件
× 当前依赖
× 当前环境
× 当前权限
</code></pre>
<p data-tool="mdnice编辑器">这使 Harness 的结构可以随着任务和环境变化，而不是不断向全局系统中永久添加模块。</p>
<p data-tool="mdnice编辑器">真正的生长，不是组件数量持续增加，而是系统能够形成更适合当前任务的能力结构。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">4.6 从动态重组到自生长闭环</span></h2>
<p data-tool="mdnice编辑器">Context、Effect、Cleanup 和 Coeffects 为动态重组提供了基础。</p>
<p data-tool="mdnice编辑器">但必须强调：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>动态重组是自生长的必要条件，不是自生长的全部。</p></blockquote>
<p data-tool="mdnice编辑器">完整的自生长至少需要五个阶段。</p>
<h3 data-tool="mdnice编辑器"><span class="content">4.6.1 第一阶段：发现能力缺口</span></h3>
<p data-tool="mdnice编辑器">Agent 首先要判断自己缺少什么。</p>
<p data-tool="mdnice编辑器">例如：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">当前没有访问某类数据的工具；</section>
</li>
<li>
<section style="color: #010101;">现有 Tool 无法处理特定协议；</section>
</li>
<li>
<section style="color: #010101;">Memory 无法支持长期任务；</section>
</li>
<li>
<section style="color: #010101;">当前模型不适合某类输入；</section>
</li>
<li>
<section style="color: #010101;">缺少项目专用的验证流程；</section>
</li>
<li>
<section style="color: #010101;">当前执行环境不满足安全要求；</section>
</li>
<li>
<section style="color: #010101;">工具调用成本或延迟过高。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">能力缺口不能只由「工具调用失败」判断。</p>
<p data-tool="mdnice编辑器">它还可能来自：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">任务规划；</section>
</li>
<li>
<section style="color: #010101;">运行指标；</section>
</li>
<li>
<section style="color: #010101;">用户反馈；</section>
</li>
<li>
<section style="color: #010101;">测试结果；</section>
</li>
<li>
<section style="color: #010101;">历史失败记录；</section>
</li>
<li>
<section style="color: #010101;">现有能力清单；</section>
</li>
<li>
<section style="color: #010101;">环境变化。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，自生长的起点不是生成代码，而是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">目标要求
-
当前能力
=
能力缺口
</code></pre>
<h3 data-tool="mdnice编辑器"><span class="content">4.6.2 第二阶段：生成或引入候选能力</span></h3>
<p data-tool="mdnice编辑器">识别缺口后，Agent 可以选择不同方式补齐能力：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">编写新的 Tool；</section>
</li>
<li>
<section style="color: #010101;">生成新的 Skill；</section>
</li>
<li>
<section style="color: #010101;">安装已有 Package；</section>
</li>
<li>
<section style="color: #010101;">包装外部 API；</section>
</li>
<li>
<section style="color: #010101;">组合已有组件；</section>
</li>
<li>
<section style="color: #010101;">替换 Memory Provider；</section>
</li>
<li>
<section style="color: #010101;">调整模型 Router；</section>
</li>
<li>
<section style="color: #010101;">创建新的工作流；</section>
</li>
<li>
<section style="color: #010101;">启动一个专用子 Agent；</section>
</li>
<li>
<section style="color: #010101;">为现有组件增加适配层。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这里的关键词是「候选」。</p>
<p data-tool="mdnice编辑器">Agent 生成的组件不能因为能够编译或加载，就自动成为系统的永久能力。</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">生成成功
≠
能力有效
≠
适合长期保留
</code></pre>
<h3 data-tool="mdnice编辑器"><span class="content">4.6.3 第三阶段：在受控环境中激活</span></h3>
<p data-tool="mdnice编辑器">候选组件应该先进入受限 Context。</p>
<p data-tool="mdnice编辑器">系统需要明确：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">它可以访问哪些目录；</section>
</li>
<li>
<section style="color: #010101;">可以调用哪些网络服务；</section>
</li>
<li>
<section style="color: #010101;">是否可以读取凭证；</section>
</li>
<li>
<section style="color: #010101;">可以注册哪些工具；</section>
</li>
<li>
<section style="color: #010101;">能否修改全局状态；</section>
</li>
<li>
<section style="color: #010101;">资源消耗上限是多少；</section>
</li>
<li>
<section style="color: #010101;">运行时间是否受限；</section>
</li>
<li>
<section style="color: #010101;">哪些副作用必须登记。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这一点尤其重要，因为扩展代码通常拥有较高权限。</p>
<p data-tool="mdnice编辑器">以 Pi 为例，其官方安全文档明确说明，内置工具和 Extension 默认继承启动 Pi 的进程权限；第三方 Package 可能执行代码或指示模型执行操作，因此需要代码审查，并在需要时依赖容器或虚拟化提供真正的隔离边界。(<a style="font-weight: bold; color: #ef7060;" href="https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/packages.md">github.com</a>)</p>
<p data-tool="mdnice编辑器">如果 Agent 开始自行生成和加载组件，权限问题只会更加突出。</p>
<p data-tool="mdnice编辑器">所以，自生长必须建立在受控运行时上，而不能建立在「默认信任所有新代码」之上。</p>
<h3 data-tool="mdnice编辑器"><span class="content">4.6.4 第四阶段：验证、保留或回滚</span></h3>
<p data-tool="mdnice编辑器">候选能力激活后，系统需要对它进行验证。</p>
<p data-tool="mdnice编辑器">验证可以包括：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">能否完成目标任务；</section>
</li>
<li>
<section style="color: #010101;">是否通过单元测试；</section>
</li>
<li>
<section style="color: #010101;">是否破坏已有功能；</section>
</li>
<li>
<section style="color: #010101;">是否产生未声明的副作用；</section>
</li>
<li>
<section style="color: #010101;">是否扩大了不必要的权限；</section>
</li>
<li>
<section style="color: #010101;">是否降低了任务成本；</section>
</li>
<li>
<section style="color: #010101;">是否提高了成功率；</section>
</li>
<li>
<section style="color: #010101;">是否造成明显的上下文膨胀；</section>
</li>
<li>
<section style="color: #010101;">是否与现有组件冲突；</section>
</li>
<li>
<section style="color: #010101;">Cleanup 是否完整。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">验证结果通常有三种：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">验证通过
    ↓
保留或固化

部分通过
    ↓
修改后重新试验

验证失败
    ↓
Cleanup + 回滚
</code></pre>
<p data-tool="mdnice编辑器">因此，自生长不是一次性的代码生成，而是一个选择过程：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Generate
→ Activate
→ Observe
→ Evaluate
→ Select
</code></pre>
<p data-tool="mdnice编辑器">没有评估的生成，只是变化。</p>
<p data-tool="mdnice编辑器">经过评估和选择的变化，才可能成为生长。</p>
<h3 data-tool="mdnice编辑器"><span class="content">4.6.5 第五阶段：沉淀、复用与淘汰</span></h3>
<p data-tool="mdnice编辑器">一次任务中的成功，不代表组件值得永久保留。</p>
<p data-tool="mdnice编辑器">系统还需要决定：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">这项能力是否跨会话有效？</section>
</li>
<li>
<section style="color: #010101;">它适用于哪些任务？</section>
</li>
<li>
<section style="color: #010101;">应该在什么条件下重新激活？</section>
</li>
<li>
<section style="color: #010101;">它依赖哪些版本？</section>
</li>
<li>
<section style="color: #010101;">它的权限范围是什么？</section>
</li>
<li>
<section style="color: #010101;">它由谁生成？</section>
</li>
<li>
<section style="color: #010101;">经过了哪些测试？</section>
</li>
<li>
<section style="color: #010101;">是否允许自动升级？</section>
</li>
<li>
<section style="color: #010101;">何时应该重新评估？</section>
</li>
<li>
<section style="color: #010101;">何时应该被淘汰？</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，一个可复用组件除了代码，还需要附带元数据：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Component
├── Implementation
├── Capability Description
├── Coeffects
├── Permissions
├── Validation Records
├── Version
├── Provenance
├── Metrics
├── Effect
└── Cleanup
</code></pre>
<p data-tool="mdnice编辑器">真正的自生长闭环应当是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">发现缺口
  ↓
生成候选能力
  ↓
隔离激活
  ↓
观察与验证
  ↓
保留或回滚
  ↓
沉淀为可复用组件
  ↓
持续评估
  ↓
升级或淘汰
</code></pre>
<hr data-tool="mdnice编辑器" />
<h1 data-tool="mdnice编辑器"><span class="content">5. Pi 与 DSH 的核心差异</span></h1>
<p data-tool="mdnice编辑器">Pi 与 DSH 并不是简单的替代关系。</p>
<p data-tool="mdnice编辑器">它们关注的是两个不同层次的问题。</p>
<section class="table-container" data-tool="mdnice编辑器">
<table>
<thead>
<tr>
<th style="color: #000000;">维度</th>
<th style="color: #000000;">Pi</th>
<th style="color: #000000;">DSH</th>
</tr>
</thead>
<tbody>
<tr style="color: #000000;">
<td>核心目标</td>
<td>构建开放、可定制的 Agent Harness</td>
<td>构建支持动态变化的组件运行时</td>
</tr>
<tr style="color: #000000;">
<td>能力来源</td>
<td>Extensions、Skills、Prompts、Packages</td>
<td>运行时组件及其依赖关系</td>
</tr>
<tr style="color: #000000;">
<td>主要变化发起者</td>
<td>用户、开发者，也可以由 Agent 辅助</td>
<td>用户、系统或 Agent</td>
</tr>
<tr style="color: #000000;">
<td>组件组织方式</td>
<td>扩展资源与 Package</td>
<td>动态依赖图</td>
</tr>
<tr style="color: #000000;">
<td>激活方式</td>
<td>启动加载、临时加载或重新加载</td>
<td>根据 Context 与 Coeffects 激活</td>
</tr>
<tr style="color: #000000;">
<td>生命周期</td>
<td>以扩展加载和配置为中心</td>
<td>Effect 与 Cleanup 对称管理</td>
</tr>
<tr style="color: #000000;">
<td>依赖治理</td>
<td>主要由扩展代码和包依赖处理</td>
<td>将运行时能力依赖显式化</td>
</tr>
<tr style="color: #000000;">
<td>失败处理</td>
<td>依赖扩展实现、进程或会话边界</td>
<td>通过 Cleanup 支持组件级回滚</td>
</tr>
<tr style="color: #000000;">
<td>演化方向</td>
<td>从固定产品走向开放平台</td>
<td>从开放平台走向受控自生长</td>
</tr>
<tr style="color: #000000;">
<td>核心价值</td>
<td>让 Harness 容易被改变</td>
<td>让 Harness 可以安全地持续改变</td>
</tr>
</tbody>
</table>
</section>
<p data-tool="mdnice编辑器">可以把两者的关系概括为：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Pi：
稳定核心
+
开放扩展点
+
能力分发机制

DSH：
组件化 Context
+
显式 Coeffects
+
可逆 Effect
+
动态生命周期
</code></pre>
<p data-tool="mdnice编辑器">Pi 解决了「能力能否加入」的问题。</p>
<p data-tool="mdnice编辑器">DSH 更关注「能力如何进入、如何协作、如何退出，以及如何在运行时形成新的结构」。</p>
<h1 data-tool="mdnice编辑器"><span class="content">6. 从可扩展到自生长，中间还差什么</span></h1>
<p data-tool="mdnice编辑器">可以把 Agent Harness 的演进分为三个阶段。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">6.1 第一阶段：固定能力</span></h2>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">模型
+
固定提示词
+
固定工具
</code></pre>
<p data-tool="mdnice编辑器">系统能够执行任务，但能力边界在设计阶段已经确定。</p>
<p data-tool="mdnice编辑器">如果缺少能力，只能由开发者修改产品代码并重新发布。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">6.2 第二阶段：开放扩展</span></h2>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">稳定核心
+
Extensions
+
Skills
+
Packages
+
开放 API
</code></pre>
<p data-tool="mdnice编辑器">用户和开发者可以持续增加能力。</p>
<p data-tool="mdnice编辑器">Agent 也可以帮助编写扩展，但扩展的发现、安装、验证和维护通常仍然依赖人工流程。</p>
<p data-tool="mdnice编辑器">Pi 代表了这一阶段的重要方向：Harness 不再是一个封闭产品，而成为可以根据个人工作流持续定制的平台。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">6.3 第三阶段：受控自生长</span></h2>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">稳定内核
+
能力缺口识别
+
候选组件生成
+
动态组件运行时
+
显式依赖
+
可逆副作用
+
隔离验证
+
自动回滚
+
能力沉淀
+
持续淘汰
</code></pre>
<p data-tool="mdnice编辑器">Agent 不再只是等待外部为它安装能力。</p>
<p data-tool="mdnice编辑器">它可以根据任务识别不足，提出新的能力结构，在受控环境中试验，并根据结果决定保留、修改还是撤销。</p>
<p data-tool="mdnice编辑器">这时，Agent 的角色从能力消费者变成了能力形成过程的参与者。</p>
<h1 data-tool="mdnice编辑器"><span class="content">7. 自生长不等于无限增长</span></h1>
<p data-tool="mdnice编辑器">「自生长」并不是 Agent 不断为自己增加工具和代码。</p>
<p data-tool="mdnice编辑器">无限增加不是生长，而是熵增。</p>
<p data-tool="mdnice编辑器">一个只会添加能力、不会清理能力的系统，最终会出现：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">工具数量不断膨胀；</section>
</li>
<li>
<section style="color: #010101;">相似能力重复实现；</section>
</li>
<li>
<section style="color: #010101;">组件版本相互冲突；</section>
</li>
<li>
<section style="color: #010101;">权限范围持续扩大；</section>
</li>
<li>
<section style="color: #010101;">上下文被大量描述占据；</section>
</li>
<li>
<section style="color: #010101;">路由规则越来越难以理解；</section>
</li>
<li>
<section style="color: #010101;">无效监听器和后台任务持续运行；</section>
</li>
<li>
<section style="color: #010101;">Agent 无法判断应该使用哪个工具；</section>
</li>
<li>
<section style="color: #010101;">系统行为逐渐不可预测。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，自生长必须同时包含四种能力：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">增加
+
选择
+
清理
+
遗忘
</code></pre>
<p data-tool="mdnice编辑器">可以进一步表示为：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">可持续生长
=
生成新能力
-
淘汰无效能力
+
重组已有能力
</code></pre>
<p data-tool="mdnice编辑器">这也是 Cleanup 和生命周期管理的重要性所在。</p>
<p data-tool="mdnice编辑器">真正成熟的 Agent 不仅要知道「我还需要什么」，还要知道：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">什么已经不需要了；</section>
</li>
<li>
<section style="color: #010101;">什么正在产生负面影响；</section>
</li>
<li>
<section style="color: #010101;">什么应该暂时停用；</section>
</li>
<li>
<section style="color: #010101;">什么可以被更简单的组件替代；</section>
</li>
<li>
<section style="color: #010101;">什么经验只适用于过去的环境。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">遗忘不是生长的反面。</p>
<p data-tool="mdnice编辑器"><strong>受控遗忘本身就是生长的一部分。</strong></p>
<h1 data-tool="mdnice编辑器"><span class="content">9. Pi 与 DSH 不是替代，而是演进</span></h1>
<p data-tool="mdnice编辑器">Pi 的价值在于证明了一件事：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>Agent Harness 不需要是一个功能固定的封闭产品。</p></blockquote>
<p data-tool="mdnice编辑器">通过开放 Extension、Skill、Prompt 和 Package，Harness 可以被用户重新塑造，也可以让 Agent 辅助编写自身需要的扩展。</p>
<p data-tool="mdnice编辑器">这已经比传统 Agent 产品向前迈出了一大步。</p>
<p data-tool="mdnice编辑器">DSH 所代表的方向，则是在此基础上进一步抽象：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如果 Agent 可以创建新能力，那么这些新能力应该如何成为运行时的一等公民？</p></blockquote>
<p data-tool="mdnice编辑器">答案不能只是把更多代码放进扩展目录。</p>
<p data-tool="mdnice编辑器">系统还需要：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">明确组件所处的 Context；</section>
</li>
<li>
<section style="color: #010101;">显式声明组件依赖的 Coeffects；</section>
</li>
<li>
<section style="color: #010101;">管理组件产生的 Effect；</section>
</li>
<li>
<section style="color: #010101;">在组件退出时执行 Cleanup；</section>
</li>
<li>
<section style="color: #010101;">根据环境变化重新计算能力拓扑；</section>
</li>
<li>
<section style="color: #010101;">对候选能力进行验证；</section>
</li>
<li>
<section style="color: #010101;">将有效能力沉淀下来；</section>
</li>
<li>
<section style="color: #010101;">将失效能力安全淘汰。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因此，二者可以形成一种递进关系：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">Pi：
让 Harness 可以被修改

        ↓

DSH：
让修改具有显式生命周期

        ↓

自生长 Agent：
让 Agent 可以发起、验证并沉淀修改
</code></pre>
<p data-tool="mdnice编辑器">从这个角度看，DSH 不是对 Pi 的否定。</p>
<p data-tool="mdnice编辑器">它是在 Pi 所代表的开放扩展思路上，将“变化”进一步提升为运行时的核心抽象。</p>
<h1 data-tool="mdnice编辑器"><span class="content">10. Harness 正在成为 Agent 的生长环境</span></h1>
<p data-tool="mdnice编辑器">如果说 Pi 的核心贡献，是把 Agent 从一个封闭产品变成一个可编程、可扩展的平台，那么 DSH 所探索的下一步，就是让 Agent 逐渐成为自身能力变化的参与者。</p>
<p data-tool="mdnice编辑器">它不只是使用已有工具，还可以：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">发现能力缺口；</section>
</li>
<li>
<section style="color: #010101;">创建候选组件；</section>
</li>
<li>
<section style="color: #010101;">调整能力组合；</section>
</li>
<li>
<section style="color: #010101;">在受控环境中试验；</section>
</li>
<li>
<section style="color: #010101;">根据结果保留或回滚；</section>
</li>
<li>
<section style="color: #010101;">将成功经验沉淀为长期能力。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">但自生长不等于无限增加。</p>
<p data-tool="mdnice编辑器">一个只会安装新工具、写入新记忆、叠加新策略的 Agent，最终只会被自己积累的复杂度拖垮。</p>
<p data-tool="mdnice编辑器">真正可持续的生长，必须同时包含：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">发现
→ 生成
→ 激活
→ 验证
→ 选择
→ 清理
→ 沉淀
→ 淘汰
</code></pre>
<p data-tool="mdnice编辑器">Pi 回答了：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如何让 Agent Harness 可以被持续扩展？</p></blockquote>
<p data-tool="mdnice编辑器">DSH 则进一步追问：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p>如何让 Agent 安全地参与自身能力的形成？</p></blockquote>
<p data-tool="mdnice编辑器">从 Pi 到 DSH，变化的不只是扩展机制，而是 Harness 的角色。</p>
<p data-tool="mdnice编辑器">它正在从承载工具与插件的工程框架，转变为支持能力试验、筛选、重组和沉淀的运行环境。</p>
<p data-tool="mdnice编辑器">未来的 Agent Harness 可能不再只是模型与工具之间的连接层。</p>
<p data-tool="mdnice编辑器">它还将成为 Agent 管理自身变化的基础设施：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">允许新能力出现；</section>
</li>
<li>
<section style="color: #010101;">阻止错误变化扩散；</section>
</li>
<li>
<section style="color: #010101;">保存经过验证的经验；</section>
</li>
<li>
<section style="color: #010101;">清除已经失效的结构；</section>
</li>
<li>
<section style="color: #010101;">在保持稳定内核的同时持续重组外围能力。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">只有当 Agent 既能增加能力，也能验证、回滚、清理和遗忘时，它才真正具备从「可扩展的软件」走向「可持续生长的系统」的可能。</p>
<p data-tool="mdnice编辑器">以上。</p>
</section>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/08/from-pi-to-dsh-how-agent-harness-evolves-from-scalable-to-self-growing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>聊聊 Harness：从 Agent 到组织</title>
		<link>https://www.phppan.com/2026/05/harness-engineering-anent-org/</link>
		<comments>https://www.phppan.com/2026/05/harness-engineering-anent-org/#comments</comments>
		<pubDate>Sat, 30 May 2026 09:35:05 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[harness]]></category>
		<category><![CDATA[harness engineering]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2501</guid>
		<description><![CDATA[我们在落地 Agent 时面临的核心矛盾，是大模型的概率生成机制与工程系统所需的绝对确定性存在天然冲突。要获取 [&#8230;]]]></description>
				<content:encoded><![CDATA[<section id="nice" style="color: #000000;" data-tool="mdnice编辑器" data-website="https://www.mdnice.com">
<p data-tool="mdnice编辑器">我们在落地 Agent 时面临的核心矛盾，是大模型的概率生成机制与工程系统所需的绝对确定性存在天然冲突。要获取大规模、可维护且值得信赖的代码，必须在系统外围构建 Harness。<strong>Harness 的本质是将不确定性转化为确定性。</strong></p>
<p data-tool="mdnice编辑器">提高信任度和可靠性需要极度压缩 Agent 的解决方案空间。我们必须放弃让模型「生成任何内容」的灵活性，转而采用包含大量技术细节的提示、规则和框架。特定的架构模式、强制执行的边界以及标准化的结构，构成了这套护栏的物理基础。</p>
<p data-tool="mdnice编辑器">当前越来越多的团队在持续快速的产生代码，而这些演示很好看，当真的进入整个软件生命周期中，就会产生混乱，当越来越多的人随着时间的推移在仓库中堆砌代码，组织就开始堆人进行 review、反复返工，最后 AI 的吞吐量被人类注意力卡死，表面上用了 Agent，实际产能没上去，维护成本还更高。</p>
<p data-tool="mdnice编辑器">当然，这是一种结果，也有人在过程中不停的构建基建，做 Harness 工程，整个代码不再是无序的扩张。从这个逻辑来讲，harness 的作用是把<strong>大模型输出从概率事件压回工程确定性的系统设计</strong>。</p>
<h1 data-tool="mdnice编辑器"><span class="content">Agent 的 Harness</span></h1>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">harness 是什么</span></h2>
<p data-tool="mdnice编辑器"><strong>很多人把 harness 比作一个操作系统，模型是 CPU，但我觉得并不是。</strong></p>
<p data-tool="mdnice编辑器">如果模型真的是 CPU，那它接收指令后的执行结果应该是绝对严格且可预测的；但大模型本质上是一个概率引擎，它在潜空间里做的是模式匹配与概率生成。因此，harness 并不是像操作系统那样去调度底层硬件资源或分配内存，它更像是一套概率过滤器和对齐机制。它依靠纯粹的工程手段，把模型那种发散的、充满不确定性的「创造力」或「幻觉」，强行压缩进一条狭窄、严谨且符合人类预期的流水线里。</p>
<p data-tool="mdnice编辑器">这种工程逻辑在实践中，体现为无处不在的防御性设计和反馈闭环。当模型吐出一串代码或一个决策时，harness 并不负责直接「运行」它，而是负责「质检」和「纠偏」。它通过静态检查、架构规则扫描、自动化测试和沙箱验证，把模型给出的「大概率正确」转化为工程上非黑即白的「通过或驳回」。正是这种让概率不断撞击确定性规则的过程，才使得最终沉淀到代码库里的产物是安全、可控且符合系统长期利益的。</p>
<p data-tool="mdnice编辑器">harness 解决确定性问题的终极目的，是为了在系统中建立无需人工干预的信任，从而真正释放 AI 的吞吐量。如果没有这套逻辑，模型生成的代码越多，人类审查的负担就越重，整个组织的运转速度依然会被人类的注意力瓶颈卡死。</p>
<p data-tool="mdnice编辑器">Martin Fowler 的博客中发表了 Thoughtworks 的技术专家的一篇文章，将 OpenAI 文章中所描述的 harness 分为三个方面：</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">上下文工程</span></h2>
<p data-tool="mdnice编辑器">上下文工程需要做到动态与静态的交织</p>
<p data-tool="mdnice编辑器">单纯依赖超长 Prompt 无法解决复杂工程问题。上下文工程的核心在于构建代码库中持续增强的知识库，并打通 Agent 对动态上下文的访问路径。</p>
<p data-tool="mdnice编辑器">静态知识库定义了系统的基础法则。我们将领域模型、API 契约和历史架构决策文档化，作为 Agent 初始化的基线上下文。动态上下文决定了 Agent 在运行时的决策质量。系统需要将实时的可观测性数据、测试覆盖率报告甚至浏览器导航状态，实时注入到 Agent 的工作流中。缺乏动态上下文的 Agent 就像蒙眼狂奔的打字机，产出的代码在语法上完美，在逻辑上完全脱离系统现状。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">架构约束</span></h2>
<p data-tool="mdnice编辑器">架构约束是确定性的防线。</p>
<p data-tool="mdnice编辑器">完全依赖 LLM 进行自我反思和代码审查，在生产环境中极度危险。架构约束必须由确定性的自定义代码检查器和结构测试来强制执行。</p>
<p data-tool="mdnice编辑器">我们通过静态分析工具拦截不合规的依赖调用，利用 AST（抽象语法树）解析确保代码分层符合规范。当 Agent 试图在 UI 层直接发起数据库连接时，确定性的检查器会立即阻断该行为，并将具体的错误堆栈和修复路径作为反馈输入给 Agent。这种混合架构确保了系统的底线由死板的规则守卫，Agent 的创造力被严格限制在安全的沙盒内。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">垃圾回收</span></h2>
<p data-tool="mdnice编辑器">垃圾回收主要是用于对抗代码熵增。</p>
<p data-tool="mdnice编辑器">完全自主的智能体引入了代码库衰败的新问题。Agent 会精准且不知疲倦地复现代码仓库中已存在的模式，包含那些不均衡或不够理想的遗留设计。随着时间的推移，这种行为不可避免地导致系统架构漂移。</p>
<p data-tool="mdnice编辑器">最初，人类开发者试图手动处理这个问题。团队过去每周五要花费 20% 的时间清理「AI 残渣」。这种依赖人力的做法毫无可扩展性。</p>
<p data-tool="mdnice编辑器">我们将资深工程师的主观品味转化为机械规则，提炼为「黄金原则」并直接编码到代码仓库中，建立了一个循环清理流程。我们强制要求使用共享的实用程序包，禁止手工编写零散的辅助工具，确保不变式集中管理。我们严禁使用猜测性的数据探测，强制验证边界或依赖类型化的 SDK，防止 Agent 基于虚幻的结构进行构建。</p>
<p data-tool="mdnice编辑器">系统定期运行一组后台 Agent 任务，扫描代码库中的偏差、更新质量等级，并发起有针对性的重构 Pull Request。这些 PR 大多可以在一分钟内完成审查并自动合并。这套机制的功能等同于内存管理中的垃圾回收。技术债务如同高息贷款，通过高频的微小重构不断偿还，远胜过让债务累积到系统崩溃。人类的架构品味一旦被捕获并规则化，就会无情地应用于每一行代码，每天自动发现并消灭不良模式。</p>
<h1 data-tool="mdnice编辑器"><span class="content">AI Agent Harness 的工程化落地</span></h1>
<p data-tool="mdnice编辑器">从几个流行的框架来看，主要是从流程强化、规格沉淀、任务编排等逻辑上来做事情。</p>
<p data-tool="mdnice编辑器">将这些逻辑拆开可以分为四个维度：</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">上下文工程</span></h2>
<p data-tool="mdnice编辑器">上下文工程主要是在规范层解决问题，其主要解决的「规则文件失控」的问题，实现规格沉淀与对齐，以及上下文工程的可控。</p>
<p data-tool="mdnice编辑器">之前，我们习惯把所有规范塞进类似于单个 <code style="color: #ef7060;">.cursorrules</code> 文件，导致 AI 上下文过载且容易忽略细节。这一层落地的第一步是建立结构化、按需加载的规范体系。主要做到如下的点：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">规范模块化</strong>：将系统架构、数据库规范、错误处理等拆分为独立的结构化文档。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">按需检索</strong>：AI 不需要每次都通读所有规范，而是根据当前所处的任务阶段，动态检索并加载所需的上下文。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">任务记忆隔离</strong>：为每个独立任务建立物理隔离的工作区和日志。AI 每次开启新会话时，只读取当前任务的精确记忆，既解决了“跨会话失忆”，又屏蔽了无关信息的干扰。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">以 Trellis 框架为例，Trellis 摒弃了单一庞大的全局提示词文件，而是采用 spec/ 目录将规范模块化（如拆分为 database-guidelines.md）。在执行任务时，它利用 tasks/ 目录下的 JSONL 配置文件，让 Agent 动态检索并按需加载上下文。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">架构约束</span></h2>
<p data-tool="mdnice编辑器">架构约束的<strong>核心逻辑：用代码约束代码，实现闭环自愈。</strong> 口头约定或纯文本规范在 AI 面前是脆弱的，它极易为了「跑通逻辑」而破坏架构分层。</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">规则代码化</strong>：将核心的架构依赖规则（例如“前端组件严禁直接调用数据库”）编写为静态分析脚本或自定义 Linter。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">带解释的强阻断</strong>：在代码提交或验证阶段强制执行这些拦截器。关键在于，报错信息不能仅仅是「检查失败」，必须输出高度结构化的指导：明确告诉 AI“为什么违反了规则”以及“正确的做法是什么”。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">自动修复</strong>：AI 读取到结构化的报错指导后，能够自动理解并修正代码，形成无需人类介入的自愈闭环。</section>
</li>
</ul>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">反馈循环</span></h2>
<p data-tool="mdnice编辑器"><strong>核心逻辑：降噪处理，防范死循环。</strong> LLM 的注意力会被长篇大论的日志（如几千行的覆盖率输出）稀释注意力，从而忽略真正致命的错误。 因此我们需要做到：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">零输出原则</strong>：改造验证脚本。如果测试通过，脚本应保持完全沉默；如果失败，只输出精简的错误堆栈和失败原因。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">强制验收清单</strong>：在 AI 试图标记任务「已完成」之前，系统应强制拦截，要求其对照需求文档逐项确认边界条件。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">防死循环干预</strong>：设定重试阈值。如果 AI 对同一文件连续修改多次且测试依然失败，系统应主动中断并强制其回滚代码、重新审视需求，防止 AI 陷入无效的「幻觉修 Bug」循环。</section>
</li>
</ul>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">熵管理</span></h2>
<p data-tool="mdnice编辑器">熵管理主要是阻断「坏模式」的指数级扩散</p>
<p data-tool="mdnice编辑器"><strong>核心逻辑：快速偿还技术债。</strong> AI 复制坏代码的速度是指数级的。一旦允许一个临时的妥协方案合入主分支，AI 会在极短时间内将其复制到整个代码库。</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">高频垃圾收集</strong>：彻底放弃“集中清技术债”的传统做法。每天必须安排固定时间，专门 Review AI 生成的代码（人工或 AI 自动），及时识别新引入的坏模式。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">规范资产的动态演进</strong>：一旦发现坏模式，立即让 AI 深度分析根因，并<strong style="color: #000000;">自动将正确的防范规则更新到规范库中</strong>。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">团队级免疫</strong>：由于规范库与代码同源管理（存在于 Git 仓库中），当这段新规则被提交后，团队其他成员拉取代码时，他们的 AI 助手就能立刻“学会”这个新技能。这把偿还技术债的动作，变成了每天自动化、可积累的系统进化。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">以 Cursor 为例，可以更新 Team Rules</p>
<h1 data-tool="mdnice编辑器"><span class="content">组织级 Harness</span></h1>
<p data-tool="mdnice编辑器">聊完 Agent 的 Harness，再聊一下组织的。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">人的角色已经变了</span></h2>
<p data-tool="mdnice编辑器">大家都知道康威定律，简单来说就是：<strong>设计系统的组织，其产生的设计受限于这些组织的沟通结构。</strong></p>
<p data-tool="mdnice编辑器">而系统设计到最后，也一定会遇到一个问题：<strong>谁来定义规则，谁来解释例外，谁来承担后果。</strong></p>
<p data-tool="mdnice编辑器">以前的软件开发分工相对稳定。PM 写需求，设计出稿，前后端分别实现，测试验证，运维发布。大家各自占一段链路，边界虽然有摩擦，但总体清楚。</p>
<p data-tool="mdnice编辑器">AI 进来以后，边界开始模糊。</p>
<p data-tool="mdnice编辑器">PM 已经可以直接产出前端原型，很多时候产出的还不是静态图，而是真能跑的页面代码。设计师也不再只是给稿子，很多交互和组件约束可以直接沉淀成生成资产。前端工程师花在纯页面搭建上的时间下降，开始更多介入状态管理、交互抽象、可维护性收拢。后端和算法也更早被拉进来，因为很多 AI 生成的原型一开始就会碰到真实数据和能力边界。</p>
<p data-tool="mdnice编辑器">这是现在很多团队正在进行的转型。</p>
<p data-tool="mdnice编辑器">如果组织还按旧的分工运转，Agent 会把协作缝隙快速放大。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">组织级 Harness 要管什么</span></h2>
<p data-tool="mdnice编辑器">我理解的组织级 harness，重点在三件事：</p>
<ol data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定义新的协作接口</strong></section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">重新分配注意力</strong></section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">把责任从「谁写了代码」改成「谁定义了系统」</strong></section>
</li>
</ol>
<h3 data-tool="mdnice编辑器"><span class="content">协作接口要前移</span></h3>
<p data-tool="mdnice编辑器">以前很多问题可以留到开发阶段再对齐。现在不行。</p>
<p data-tool="mdnice编辑器">因为 PM 通过 AI 已经能直接产出前端代码，需求不再是文字说明，而可能是一个可交互原型；设计规范也不再只是 Figma 标注，而是可以半自动映射到组件约束；后端接口能力如果不提前讲清楚，前面的生成很容易一路偏到错误方向。</p>
<p data-tool="mdnice编辑器">所以组织里的评审必须前移，重点也得改。</p>
<p data-tool="mdnice编辑器">过去的需求评审，很多时候在讨论功能要不要做。现在要多讨论三件事：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">验收标准到底是什么</section>
</li>
<li>
<section style="color: #010101;">哪些边界不能突破</section>
</li>
<li>
<section style="color: #010101;">哪些部分允许先用原型推进，哪些必须工程化收拢后才能上线</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这几个东西不提前定，后面会出现一个很常见的问题：原型阶段看起来进展飞快，进入工程化后才发现返工巨大。</p>
<h3 data-tool="mdnice编辑器"><span class="content">注意力要重新分配</span></h3>
<p data-tool="mdnice编辑器">我现在越来越少鼓励资深工程师花时间逐行抠低风险代码。</p>
<p data-tool="mdnice编辑器">这不是说 review 不重要，而是注意力要贵着用。</p>
<p data-tool="mdnice编辑器">在 Agent 环境里，重要的工作变成了：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">定义验收标准</section>
</li>
<li>
<section style="color: #010101;">设计架构边界</section>
</li>
<li>
<section style="color: #010101;">提炼黄金原则</section>
</li>
<li>
<section style="color: #010101;">识别系统性失败信号</section>
</li>
<li>
<section style="color: #010101;">决定哪些异常值得阻塞主流程</section>
</li>
<li>
<section style="color: #010101;">审核高风险改动和高影响面重构</section>
</li>
</ul>
<p data-tool="mdnice编辑器">反过来，低风险、重复性、局部性的东西，应该尽量交给自动化校验和后台清理任务。</p>
<p data-tool="mdnice编辑器">如果一个组织还在让最贵的人力去看大批格式化差异、小工具改名、重复样板代码，那 harness 基本等于没有。</p>
<h3 data-tool="mdnice编辑器"><span class="content">责任归属要重写</span></h3>
<p data-tool="mdnice编辑器"><strong>在 AI-Native 组织里，谁对结果负责？</strong></p>
<p data-tool="mdnice编辑器">PM 产出了页面代码，前端做了工程化收拢，Agent 自动补了测试，清理 Agent 又改了一轮共享工具。最后线上出问题，算谁的？</p>
<p data-tool="mdnice编辑器">如果这个问题没有明确答案，团队会很快进入防御状态。每个人都怕接 AI 产出的锅，于是流程开始重新变重，所有人都试图把责任往后传。</p>
<p data-tool="mdnice编辑器">所以组织级 harness 一定要明确责任模型。</p>
<p data-tool="mdnice编辑器">可以按三层分：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">需求责任</strong>：谁定义了目标与验收标准，谁负责需求正确性</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">架构责任</strong>：谁定义了边界、模式和约束，谁负责系统一致性</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">发布责任</strong>：谁决定进入生产环境，谁负责风险接受</section>
</li>
</ul>
<p data-tool="mdnice编辑器">不要再执着于「谁手写了这行代码」。就像团队管理一样，最后拍板的人担责。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #ffffff;">可落地的 AI-Native 研发流程</span></h2>
<p data-tool="mdnice编辑器">以下为我们当前在跑的流程：</p>
<h3 data-tool="mdnice编辑器"><span class="content">需求生成</span></h3>
<p data-tool="mdnice编辑器">第一步由 PM 主导，但交付物不再只是 PRD，而是<strong>带验收标准的可运行原型</strong>。</p>
<p data-tool="mdnice编辑器">但是，原型代码不等于可直接上线代码。它的价值是澄清需求、暴露分歧、提前感知交互复杂度。</p>
<p data-tool="mdnice编辑器">所以 PM 可以生成，但不能默认拥有工程决策权。最终所有的代码都需要前端工程师构建的工具链条，以及 AI 和人工的审核及合入。</p>
<h3 data-tool="mdnice编辑器"><span class="content">联合评审</span></h3>
<p data-tool="mdnice编辑器">第二步是全员参与的需求评审与架构设计。设计、前端、后端、算法都要尽早介入。</p>
<p data-tool="mdnice编辑器">这个阶段重点不是抠实现细节，而是确定：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">用户路径是否成立</section>
</li>
<li>
<section style="color: #010101;">数据流怎么走</section>
</li>
<li>
<section style="color: #010101;">状态边界怎么划</section>
</li>
<li>
<section style="color: #010101;">哪些能力用现有服务承接</section>
</li>
<li>
<section style="color: #010101;">哪些模块需要新增抽象</section>
</li>
<li>
<section style="color: #010101;">风险点在哪</section>
</li>
<li>
<section style="color: #010101;">验收怎么自动化</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这这一步的产出结构化进仓库，因为后面它会直接成为 Agent 的约束输入。</p>
<h3 data-tool="mdnice编辑器"><span class="content">工程收拢</span></h3>
<p data-tool="mdnice编辑器">第三步是工程化整合。这个阶段前端、后端、算法开始把前面的原型和需求收敛进正式系统。</p>
<p data-tool="mdnice编辑器">这里 Agent 会大量参与，但人类不能退出。重点工作包括：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">把原型重构进现有组件和模块体系</section>
</li>
<li>
<section style="color: #010101;">校正状态管理、错误处理、埋点、权限、监控</section>
</li>
<li>
<section style="color: #010101;">对接真实接口和算法能力</section>
</li>
<li>
<section style="color: #010101;">补齐类型、边界验证和回归测试</section>
</li>
<li>
<section style="color: #010101;">处理跨模块影响面</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这一段最考验 harness，因为原型代码最容易带着局部最优、全局失真、风格漂移的问题冲进主仓。</p>
<h3 data-tool="mdnice编辑器"><span class="content">自动验证与灰度</span></h3>
<p data-tool="mdnice编辑器">最后一步是自动化测试、灰度发布和反馈回收。</p>
<p data-tool="mdnice编辑器">这一步先由专门的工程团队来负责，加入部分的 AI 成分，固化系统。</p>
<h1 data-tool="mdnice编辑器"><span class="content">从 Agent 到组织，真正难的是控制系统</span></h1>
<p data-tool="mdnice编辑器">很多人以为 AI 落地的核心挑战在模型能力、成本或者工具接入。我现在看，最大挑战更集中在三个词：<strong>环境、反馈回路、控制系统。</strong></p>
<p data-tool="mdnice编辑器">环境决定 Agent 看到了什么、能做什么、不能做什么。</p>
<p data-tool="mdnice编辑器">反馈回路决定错误会被放大，还是会被系统吸收成改进信号。</p>
<p data-tool="mdnice编辑器">控制系统决定生成能力增长之后，组织是变得更稳，还是更乱。</p>
<p data-tool="mdnice编辑器">这三个东西做不好，模型再强也只是更快地产生问题。</p>
<p data-tool="mdnice编辑器">做得好，哪怕模型能力没到最顶尖，系统一样能稳定进化。因为工程上真正稀缺的，从来不是一次惊艳输出，而是长期重复地产出靠谱结果。</p>
<h1 data-tool="mdnice编辑器"><span class="content">组织的 AI-Native 化</span></h1>
<p data-tool="mdnice编辑器">组织的 AI-Native 化也是慢慢进货，逐步推进的，先从小范围试起，再根据结果不断调整规则和流程。并且各家有各家的风格和气质。</p>
<p data-tool="mdnice编辑器">第一，<strong>选一条链路打透</strong>。不要一开始就全组织铺开。先找一个协作关系清楚、反馈周期短、风险相对可控的场景，比如中后台、运营工具、内部系统，或者低风险服务改造。重点不是让 AI 多写代码，而是先验证：信息怎么给、边界怎么定、错误怎么发现、问题怎么清理。</p>
<p data-tool="mdnice编辑器">第二，<strong>先改规则，再谈效率</strong>。很多团队一上来就问产能能提升多少，但更重要的是：规则有没有沉淀下来，错误能不能回流，坏模式能不能及时发现并清掉。如果这些没做好，所谓提效往往只是把问题推后，甚至把混乱放大。</p>
<p data-tool="mdnice编辑器">第三，<strong>把人的位置往上移</strong>。资深工程师要逐渐从大量写代码，转向定规则、画边界、看反馈；技术管理者要从盯人和排期，转向设计流程、分层风险、明确责任；产品可以更早参与原型，但不能越过工程判断。</p>
<p data-tool="mdnice编辑器">组织真正变成 AI-Native，不是因为每个人都在用 Agent，而是协作方式已经围绕 Agent 被重新设计过。</p>
<p data-tool="mdnice编辑器">模型当然重要，但不是决定性因素。真正拉开差距的，是谁先意识到：Agent 不是一个更快的开发者，而是一个高吞吐的生产单元。它会放大环境本身。规则清楚，它就放大规则；流程混乱，它就放大混乱。</p>
<p data-tool="mdnice编辑器">所以到最后，harness 这件事谈的根本不只是 AI。</p>
<p data-tool="mdnice编辑器">谈的是工程纪律怎么重新编码。</p>
<p data-tool="mdnice编辑器">谈的是组织协作怎么重新布线。</p>
<p data-tool="mdnice编辑器">谈的是我们怎么把概率生成系统，放进一个仍然要求长期维护、长期演进、长期负责的软件世界。</p>
<p data-tool="mdnice编辑器">这是我理解的「从 Agent 到组织」。</p>
<p data-tool="mdnice编辑器">以上。</p>
</section>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/05/harness-engineering-anent-org/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入 Claude Code 源码了解其记忆系统</title>
		<link>https://www.phppan.com/2026/04/claude-code-source-memory/</link>
		<comments>https://www.phppan.com/2026/04/claude-code-source-memory/#comments</comments>
		<pubDate>Sat, 04 Apr 2026 01:19:58 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[ClaudeCode]]></category>
		<category><![CDATA[harness engineering]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2484</guid>
		<description><![CDATA[最近做 Agent 的同学应该大部分都有研读 Claude Code 泄漏的源码，网上出了各种 AI 加持下的 [&#8230;]]]></description>
				<content:encoded><![CDATA[<section id="nice" data-tool="mdnice编辑器" data-website="https://www.mdnice.com">
<section id="nice" style="color: #000000;" data-tool="mdnice编辑器" data-website="https://www.mdnice.com">
<p data-tool="mdnice编辑器">最近做 Agent 的同学应该大部分都有研读 Claude Code 泄漏的源码，网上出了各种 AI 加持下的各种解读，教程，细节分析，甚至包括换了一种语言实现的版本，如 Python，Go，Rust 等等。感觉有点「一鲸落，万物生」的感觉。</p>
<p data-tool="mdnice编辑器">之前学习了 Claude Code 的系统提示词，写了一篇关于记忆系统的提示词。今天我们再深入其源码，看看其实现的细节。</p>
<p data-tool="mdnice编辑器">从其源码来看，</p>
<p data-tool="mdnice编辑器">Claude Code 这套记忆系统把几类完全不同的问题拆开处理了：长期记忆、当前轮相关记忆、会话压缩摘要、子代理独立记忆。和 OpenClaw 不同，OpenClaw 使用了统一的 Memory Service，加上一个向量库做检索，Claude Code 走的是另一条路：<strong style="color: #0e88eb;">文件系统优先，分层清晰，召回时机明确，代价可控</strong>。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">1. Claude Code 到底要记了什么</span></h1>
<p data-tool="mdnice编辑器">在 memoryTypes.ts#L14-L31 里，长期记忆的类型是的四类：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">user</code></section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">feedback</code></section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">project</code></section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">reference</code></section>
</li>
</ul>
<p data-tool="mdnice编辑器">这四类东西有一个共同点：它们都<strong style="color: #0e88eb;">不容易从当前代码状态直接推导出来</strong>。用户习惯、项目背景、团队约束、外部系统入口，这些信息不写下来，下次对话就丢了。反过来，代码结构、文件路径、Git 历史、当前临时任务，这些内容源码里明确要求不要进长期记忆，因为它们本来就有权威来源。memoryTypes.ts#L183-L195</p>
<p data-tool="mdnice编辑器">记忆系统只该保存「代码外的信息」和「会跨轮次继续影响决策的信息」。以编程为例，当我们把代码事实也塞进去，后面一定会出现双份真相。你会遇到一个很尴尬的局面：代码说 A，memory 说 B，模型开始摇摆。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">2. 四层分工</span></h1>
<p data-tool="mdnice编辑器">第一层是 <code style="color: #0e8aeb;">auto memory / team memory</code>。这是长期记忆，负责跨会话保存信息。目录逻辑在 paths.ts#L79-L259 和 teamMemPaths.ts#L66-L94。</p>
<p data-tool="mdnice编辑器">第二层是 <code style="color: #0e8aeb;">relevant memories</code>。这一层不关心长期存储，它只负责一件事：用户当前这一问，应该把哪几条历史记忆临时塞进上下文。入口在 findRelevantMemories.ts#L39-L141 和 attachments.ts#L2197-L2425。</p>
<p data-tool="mdnice编辑器">第三层是 <code style="color: #0e8aeb;">session memory</code>。这层服务的是长会话压缩，不负责跨会话记忆。位于当前 session 下的 <code style="color: #0e8aeb;">summary.md</code>。sessionMemory.ts#L183-L350</p>
<p data-tool="mdnice编辑器">第四层是 <code style="color: #0e8aeb;">agent memory</code>。子代理如果要持久化自己的经验，可以放 user/project/local 三种 scope 的独立目录。agentMemory.ts#L12-L177</p>
<p data-tool="mdnice编辑器">这四层拆开之后，很多设计选择就顺了：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">长期记忆用文件，便于审计和手工修复</section>
</li>
<li>
<section style="color: #010101;">当前轮召回走轻量检索，减少 prompt 污染</section>
</li>
<li>
<section style="color: #010101;">长会话压缩用单独 summary，避免每次 compact 都从头总结</section>
</li>
<li>
<section style="color: #010101;">子代理隔离状态，减少串味</section>
</li>
</ul>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">3. 长期记忆为什么选文件</span></h1>
<p data-tool="mdnice编辑器">Claude Code 的长期记忆是使用的 Markdown 文件。每条记忆一个文件，外加一个 <code style="color: #0e8aeb;">MEMORY.md</code> 入口索引。这部分规则在 memdir.ts#L199-L316 里写得很明白。</p>
<p data-tool="mdnice编辑器">源码里的写入约束是这样的：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-string" style="color: #98c379;">'## How to save memories'</span>,
<span class="hljs-string" style="color: #98c379;">''</span>,
<span class="hljs-string" style="color: #98c379;">'Saving a memory is a two-step process:'</span>,
<span class="hljs-string" style="color: #98c379;">''</span>,
<span class="hljs-string" style="color: #98c379;">'**Step 1** — write the memory to its own file (e.g., `user_role.md`, `feedback_testing.md`) using this frontmatter format:'</span>,
<span class="hljs-string" style="color: #98c379;">''</span>,
...MEMORY_FRONTMATTER_EXAMPLE,
<span class="hljs-string" style="color: #98c379;">''</span>,
<span class="hljs-string" style="color: #98c379;">`**Step 2** — add a pointer to that file in \`<span class="hljs-subst" style="color: #e06c75;">${ENTRYPOINT_NAME}</span>\`. \`<span class="hljs-subst" style="color: #e06c75;">${ENTRYPOINT_NAME}</span>\` is an index, not a memory — each entry should be one line, under ~150 characters: \`- [Title](file.md) — one-line hook\`. It has no frontmatter. Never write memory content directly into \`<span class="hljs-subst" style="color: #e06c75;">${ENTRYPOINT_NAME}</span>\`.`</span>,
</code></pre>
<p data-tool="mdnice编辑器">实现位置见 memdir.ts#L219-L230。</p>
<p data-tool="mdnice编辑器">还有有三个工程判断。</p>
<p data-tool="mdnice编辑器">第一，<code style="color: #0e8aeb;">MEMORY.md</code> 只是索引，不承载正文。如果把所有记忆都堆到一个大文件里，前期简单，后期灾难。Claude Code 从一开始就做拆分，每条记忆单文件，这样更新一条信息时不会引起全量重写。</p>
<p data-tool="mdnice编辑器">第二，frontmatter 强制有 <code style="color: #0e8aeb;">description</code> 字段，这个字段后面要参与召回。很多团队做知识条目，只写正文，不写检索摘要，最后靠 embedding 硬扛。Claude Code 反过来，它要求记忆写入阶段就产出一条高质量摘要。召回质量在写入那一刻就埋下去了。</p>
<p data-tool="mdnice编辑器">第三，完全基于文件系统，调试成本低。你可以直接去目录里看文件，团队同步时还能走 Git 或远端同步链路。数据库方案最大的问题不在性能，在可观察性。出了问题你要查 schema、查索引、查 embedding 版本、查写入日志，排障很慢。</p>
<p data-tool="mdnice编辑器">文件方案当然也有代价。文件一多，目录扫描成本会上升；<code style="color: #0e8aeb;">MEMORY.md</code> 入口过长也会逼近 prompt token 上限。Claude Code 后面靠动态召回机制兜住了这个问题，这个设计是连起来看的。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">4. 写入链路</span></h1>
<p data-tool="mdnice编辑器">它怎么把记忆真正落盘</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">4.1 主模型直接写</span></h2>
<p data-tool="mdnice编辑器">长期记忆的第一条写入链路，是主模型自己写。系统 prompt 里已经告诉它记忆目录在哪、允许写什么、怎么写文件、什么时候写。</p>
<p data-tool="mdnice编辑器"><code style="color: #0e8aeb;">loadMemoryPrompt()</code> 会把 memory rules 注入系统提示词，入口在 [loadMemoryPrompt] memdir.ts#L419-L507。这一段 prompt 并没有替模型做决策，它只是把写入协议放进脑子里：目录、类型、索引格式、读取时机、失效校验。</p>
<p data-tool="mdnice编辑器">这意味着 Claude Code 对模型的假设很明确：模型可以自己判断「这条信息值不值得保存」，然后调用写文件工具去落盘。写入不是一个外置 API，写入就是普通文件操作。</p>
<p data-tool="mdnice编辑器">这条路有个好处：反馈延迟很低。用户刚说完「记住这个偏好」，主模型当轮就能写，不用等后台任务。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">4.2 后台抽取器补写</span></h2>
<p data-tool="mdnice编辑器">如果主模型这一轮没动手写，系统会在 turn end 触发后台抽取器。stop hook 在 stopHooks.ts#L141-L156：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-keyword" style="color: #c678dd;">if</span> (
  feature(<span class="hljs-string" style="color: #98c379;">'EXTRACT_MEMORIES'</span>) &amp;&amp;
  !toolUseContext.agentId &amp;&amp;
  isExtractModeActive()
) {
  <span class="hljs-built_in" style="color: #e6c07b;">void</span> extractMemoriesModule!.executeExtractMemories(
    stopHookContext,
    toolUseContext.appendSystemMessage,
  )
}
</code></pre>
<p data-tool="mdnice编辑器">真正逻辑在 extractMemories.ts#L329-L567。</p>
<p data-tool="mdnice编辑器">这条链路里最重要的一段判断是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-keyword" style="color: #c678dd;">if</span> (hasMemoryWritesSince(messages, lastMemoryMessageUuid)) {
  logForDebugging(
    <span class="hljs-string" style="color: #98c379;">'[extractMemories] skipping — conversation already wrote to memory files'</span>,
  )
  ...
  <span class="hljs-keyword" style="color: #c678dd;">return</span>
}
</code></pre>
<p data-tool="mdnice编辑器">位置见 extractMemories.ts#L345-L360。</p>
<p data-tool="mdnice编辑器">它防的是双写。主模型已经写过，后台抽取器就别再重做一遍。很多系统做异步归档时忘了这件事，最后要么生成重复记忆，要么覆盖用户刚刚确认的内容。</p>
<p data-tool="mdnice编辑器">后台抽取器的权限也非常收敛。<code style="color: #0e8aeb;">createAutoMemCanUseTool()</code> 明确规定，只准：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">Read / Grep / Glob</section>
</li>
<li>
<section style="color: #010101;">只读 Bash</section>
</li>
<li>
<section style="color: #010101;">memory 目录内的 Edit / Write</section>
</li>
</ul>
<p data-tool="mdnice编辑器">实现见 [createAutoMemCanUseTool] extractMemories.ts#L166-L222。</p>
<p data-tool="mdnice编辑器">extractor 的职责：它只做归档，不许顺手验证代码，不许顺手修改业务文件，不许借机跑工具链。权限如果不锁死，后台代理迟早会从归档器膨胀成第二个主代理。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">4.3 KAIROS 下的写法</span></h2>
<p data-tool="mdnice编辑器">KAIROS 模式更有意思。它不要求模型实时维护 <code style="color: #0e8aeb;">MEMORY.md</code>，新记忆先按天追加到日志文件里。规则在 [buildAssistantDailyLogPrompt] memdir.ts#L318-L370。</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-string" style="color: #98c379;">"This session is long-lived. As you work, record anything worth remembering by **appending** to today's daily log file:"</span>,
<span class="hljs-string" style="color: #98c379;">` \`<span class="hljs-subst" style="color: #e06c75;">${logPathPattern}</span>\` `</span>,
<span class="hljs-string" style="color: #98c379;">'Write each entry as a short timestamped bullet. Create the file (and parent directories) on first write if it does not exist. Do not rewrite or reorganize the log — it is append-only. A separate nightly process distills these logs into `MEMORY.md` and topic files.'</span>,
</code></pre>
<p data-tool="mdnice编辑器">这条策略很适合长驻 Agent。会话存活时间长时，频繁重写 topic files 和索引很贵，冲突也多。先写 append-only 日志，夜间再蒸馏，吞吐更稳，模型也更不容易在白天工作时把记忆目录写乱。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">5. 召回链路</span></h1>
<p data-tool="mdnice编辑器">它怎么决定哪段记忆该进来</p>
<p data-tool="mdnice编辑器">Claude Code 的召回要分成两种看。</p>
<p data-tool="mdnice编辑器">一种是静态注入，也就是固定随上下文加载的那些东西。另一种是动态召回，根据当前 query 临时挑选最相关的记忆文件。</p>
<p data-tool="mdnice编辑器">很多系统只做前者，结果上下文越来越肥。很多系统只做后者，结果基本行为约束丢了。Claude Code 两条都做。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">5.1 静态注入</span></h2>
<p data-tool="mdnice编辑器"><code style="color: #0e8aeb;">getUserContext()</code> 会构造一个 <code style="color: #0e8aeb;">claudeMd</code> 字段，位置在 context.ts#L155-L188。</p>
<p data-tool="mdnice编辑器">核心调用是：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-keyword" style="color: #c678dd;">const</span> claudeMd = shouldDisableClaudeMd
  ? <span class="hljs-literal" style="color: #56b6c2;">null</span>
  : getClaudeMds(filterInjectedMemoryFiles(<span class="hljs-keyword" style="color: #c678dd;">await</span> getMemoryFiles()))
</code></pre>
<p data-tool="mdnice编辑器"><code style="color: #0e8aeb;">getMemoryFiles()</code> 的实现很长，在 claudemd.ts#L790-L1075。它会统一加载：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">Managed 指令</section>
</li>
<li>
<section style="color: #010101;">User 指令</section>
</li>
<li>
<section style="color: #010101;">Project 指令</section>
</li>
<li>
<section style="color: #010101;">Local 指令</section>
</li>
<li>
<section style="color: #010101;">AutoMem 的 <code style="color: #0e8aeb;">MEMORY.md</code></section>
</li>
<li>
<section style="color: #010101;">TeamMem 的 <code style="color: #0e8aeb;">MEMORY.md</code></section>
</li>
</ul>
<p data-tool="mdnice编辑器">然后 <code style="color: #0e8aeb;">getClaudeMds()</code> 把这些文件串成提示词内容，[getClaudeMds] claudemd.ts#L1153-L1195。</p>
<p data-tool="mdnice编辑器">它给模型一个稳定的全局工作框架。它会知道项目规则、用户偏好、团队共享记忆索引。它适合放那些「大方向会持续生效」的内容。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">5.2 动态召回</span></h2>
<p data-tool="mdnice编辑器">静态注入解决不了所有问题。长期记忆正文一多，全部塞进 prompt 代价太高。Claude Code 的处理方式，是每轮用户发言后启动一个相关记忆预取。</p>
<p data-tool="mdnice编辑器">入口在 query.ts#L297-L304：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;">using pendingMemoryPrefetch = startRelevantMemoryPrefetch(
  state.messages,
  state.toolUseContext,
)
</code></pre>
<p data-tool="mdnice编辑器">这个预取不会阻塞主流程。到后面条件满足时再消费，query.ts#L1595-L1617。</p>
<p data-tool="mdnice编辑器">真正检索逻辑在 attachments.ts#L2197-L2425。它会先决定搜索哪个目录：如果用户显式提到某个 agent，就搜 agent memory；否则搜 auto memory。</p>
<p data-tool="mdnice编辑器">然后调用 [findRelevantMemories] findRelevantMemories.ts#L39-L141。</p>
<p data-tool="mdnice编辑器">这里最有意思的点在于，它没有用向量库。它的步骤是：</p>
<ol data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><code style="color: #0e8aeb;">scanMemoryFiles()</code> 扫 memory 目录里的 <code style="color: #0e8aeb;">.md</code> 文件，读 frontmatter，产出一个 manifest<br />
见 memoryScan.ts#L35-L94</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">把 <code style="color: #0e8aeb;">用户 query + manifest</code> 发给一个 sideQuery 模型<br />
见 findRelevantMemories.ts#L77-L141</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">让这个模型返回最多 5 个文件名</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">再去读取这些文件正文，截断到限定行数和字节数<br />
见 [readMemoriesForSurfacing] attachments.ts#L2280-L2333</p>
</section>
</li>
</ol>
<p data-tool="mdnice编辑器">这套方案的好处：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">没有 embedding 构建成本</section>
</li>
<li>
<section style="color: #010101;">没有索引维护复杂度</section>
</li>
<li>
<section style="color: #010101;">manifest 很小，side query 很快</section>
</li>
<li>
<section style="color: #010101;">召回逻辑对开发者可见，容易调</section>
</li>
</ul>
<p data-tool="mdnice编辑器">缺点也明确。召回质量强依赖 frontmatter 的 <code style="color: #0e8aeb;">description</code>。写入时 description 写差了，后面召回一定差。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">6. 记忆怎么进入上下文</span></h1>
<p data-tool="mdnice编辑器">不是一处注入，是四处入口</p>
<p data-tool="mdnice编辑器">很多人看 Agent 源码时老在问「上下文是在什么地方拼进去的」。这个问题本身就有误导性。Claude Code 里记忆的注入入口不止一个。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">6.1 system prompt 入口</span></h2>
<p data-tool="mdnice编辑器">第一处是 system prompt。这里进来的内容主要是「记忆系统的使用规则」，比如什么时候读、什么时候存、什么时候验证失效。对应实现是 prompts.ts#L492-L527 调 <code style="color: #0e8aeb;">loadMemoryPrompt()</code>。</p>
<p data-tool="mdnice编辑器">这是行为层指令。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">6.2 user context 入口</span></h2>
<p data-tool="mdnice编辑器">第二处是 <code style="color: #0e8aeb;">getUserContext()</code> 构造的 <code style="color: #0e8aeb;">claudeMd</code>。这里进来的是 <code style="color: #0e8aeb;">CLAUDE.md</code>、rules、<code style="color: #0e8aeb;">MEMORY.md</code> 这种比较稳定的文本。context.ts#L155-L188</p>
<p data-tool="mdnice编辑器">这是稳定背景层。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">6.3 attachment 入口</span></h2>
<p data-tool="mdnice编辑器">第三处是 relevant memory attachment。被召回的正文不会直接拼到 <code style="color: #0e8aeb;">claudeMd</code>，而是先变成 attachment，再由 messages.ts#L3743-L3756 包装成 <code style="color: #0e8aeb;">&lt;system-reminder&gt;</code>。</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs" style="color: #abb2bf;"><span class="hljs-keyword" style="color: #c678dd;">return</span> wrapMessagesInSystemReminder(
  attachment.memories.map(<span class="hljs-function"><span class="hljs-params">m</span> =&gt;</span> {
    <span class="hljs-keyword" style="color: #c678dd;">const</span> header = m.header ?? memoryHeader(m.path, m.mtimeMs)
    <span class="hljs-keyword" style="color: #c678dd;">return</span> createUserMessage({
      content: <span class="hljs-string" style="color: #98c379;">`<span class="hljs-subst" style="color: #e06c75;">${header}</span>\n\n<span class="hljs-subst" style="color: #e06c75;">${m.content}</span>`</span>,
      isMeta: <span class="hljs-literal" style="color: #56b6c2;">true</span>,
    })
  }),
)
</code></pre>
<p data-tool="mdnice编辑器">这意味着这些记忆是临时的、按轮次加载的、带 freshness header 的系统提醒。它的优先级和普通用户消息不同。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">6.4 compact summary 入口</span></h2>
<p data-tool="mdnice编辑器">第四处是 session memory compact。上下文过长后，系统会把会话前半段替换为一条 summary message，summary 内容来自 <code style="color: #0e8aeb;">summary.md</code> 的裁剪版。sessionMemoryCompact.ts#L437-L503</p>
<p data-tool="mdnice编辑器">这是上下文续命层。</p>
<p data-tool="mdnice编辑器">四处入口分工以后，就能看明白为什么 Claude Code 的行为相对稳定：规则、稳定背景、临时相关信息、压缩摘要，各走各的通道，互相不抢角色。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">7. 真正的压缩发生在哪里</span></h1>
<p data-tool="mdnice编辑器">很多人一听「记忆系统」，第一反应是长期 memory 压缩。Claude Code 里最成熟的压缩逻辑，实际上落在 session memory 上。</p>
<p data-tool="mdnice编辑器">前面说过，session memory 是 <code style="color: #0e8aeb;">summary.md</code>，它本身就是会话结构化摘要。维护逻辑在 sessionMemory.ts#L272-L350。</p>
<p data-tool="mdnice编辑器">当上下文真的不够时，系统优先尝试 <code style="color: #0e8aeb;">trySessionMemoryCompaction()</code>，sessionMemoryCompact.ts#L514-L619。</p>
<p data-tool="mdnice编辑器">它的动作顺序：</p>
<ol data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">先确认 session memory 功能和 compact 功能都开着</section>
</li>
<li>
<section style="color: #010101;">等待正在进行中的 session memory 抽取结束</section>
</li>
<li>
<section style="color: #010101;">读取 <code style="color: #0e8aeb;">summary.md</code></section>
</li>
<li>
<section style="color: #010101;">如果还是空模板，放弃，退回传统 compact</section>
</li>
<li>
<section style="color: #010101;">计算需要保留的 recent messages 窗口</section>
</li>
<li>
<section style="color: #010101;">用 <code style="color: #0e8aeb;">summary.md</code> 的裁剪版构造 compact summary</section>
</li>
<li>
<section style="color: #010101;">组装 <code style="color: #0e8aeb;">boundary + summary + recent messages + attachments + hooks</code></section>
</li>
</ol>
<p data-tool="mdnice编辑器">这里的「保留 recent messages」特别关键。作者没有图省事把所有旧消息都抹掉，而是保留一段最近窗口。窗口大小由 [DEFAULT_SM_COMPACT_CONFIG] sessionMemoryCompact.ts#L56-L66 定义，默认：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">minTokens = 10000</code></section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">minTextBlockMessages = 5</code></section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">maxTokens = 40000</code></section>
</li>
</ul>
<p data-tool="mdnice编辑器">保留窗口的计算在 [calculateMessagesToKeepIndex] sessionMemoryCompact.ts#L324-L397。</p>
<p data-tool="mdnice编辑器">这个策略解决的问题是：<strong style="color: #0e88eb;">摘要永远会损失细节</strong>，最近一段工作现场最好保留原始消息，模型续做时不至于失真。要是所有内容都只剩 summary，模型会失去工具调用上下文、局部错误信息、最近的计划变更。</p>
<p data-tool="mdnice编辑器">更细的一层防御在 <code style="color: #0e8aeb;">adjustIndexToPreserveAPIInvariants()</code>。 sessionMemoryCompact.ts#L232-L314</p>
<p data-tool="mdnice编辑器">它干的事情很硬核，也很必要：如果最近保留窗口里出现了 <code style="color: #0e8aeb;">tool_result</code>，系统必须把匹配的 <code style="color: #0e8aeb;">tool_use</code> 也补进来；如果 assistant 消息因为流式输出被拆成多个共享 <code style="color: #0e8aeb;">message.id</code> 的块，thinking 和 tool_use 也要一起补齐。否则 compact 后发给 API 的消息链会断，直接报错。</p>
<p data-tool="mdnice编辑器">这一段代码说明作者踩过坑，或者至少认真想过 API 侧不变量。很多开源 Agent 框架在消息压缩这里写得很草，最后线上 bug 都长一个样：tool result 找不到 parent，thinking 丢了，message 合并失败。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">8. session memory 自己也会被裁剪</span></h1>
<p data-tool="mdnice编辑器">就算 <code style="color: #0e8aeb;">summary.md</code> 已经是摘要，compact 时还会再做一次 section 级裁剪。逻辑在 [truncateSessionMemoryForCompact] prompts.ts#L249-L295。</p>
<p data-tool="mdnice编辑器">过程如下：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">按 <code style="color: #0e8aeb;"># section</code> 拆段</section>
</li>
<li>
<section style="color: #010101;">每个 section 允许的大小用 <code style="color: #0e8aeb;">MAX_SECTION_LENGTH * 4</code> 粗略换算成字符数</section>
</li>
<li>
<section style="color: #010101;">超过就按行保留前半部分</section>
</li>
<li>
<section style="color: #010101;">最后插入 <code style="color: #0e8aeb;">[... section truncated for length ...]</code></section>
</li>
</ul>
<p data-tool="mdnice编辑器">实际截断函数见 [flushSessionSection] prompts.ts#L298-L324。</p>
<p data-tool="mdnice编辑器">这套逻辑谈不上优雅，语义理解也谈不上深入，但它有一个优点：非常稳。系统真的到了上下文极限时，保底截断总比把整个 compact 失败掉强。工程里很多时候要的是「退化可接受」，不是「完美压缩」。</p>
<p data-tool="mdnice编辑器">然后 <code style="color: #0e8aeb;">createCompactionResultFromSessionMemory()</code> 把裁剪后的 session memory 包成 summary message。 sessionMemoryCompact.ts#L437-L503</p>
<p data-tool="mdnice编辑器">这里还有一个细节：如果发生过裁剪，它会额外附一句话，告诉模型和人类完整 session memory 文件路径在哪。排障时你可以直接打开原始 <code style="color: #0e8aeb;">summary.md</code>，不用猜裁掉了什么。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">9. KAIROS 的压缩逻辑和普通模式不一样</span></h1>
<p data-tool="mdnice编辑器">KAIROS 里还有另一种「压缩」，它压的不是当前上下文，而是长期事件流。</p>
<p data-tool="mdnice编辑器">在 memdir.ts#L321-L349 里能看到，KAIROS 模式下白天写的是 append-only daily log。到夜间，<code style="color: #0e8aeb;">/dream</code> 流程会把这些日志蒸馏成 topic files 和 <code style="color: #0e8aeb;">MEMORY.md</code>。</p>
<p data-tool="mdnice编辑器">这是另一类压缩：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">输入是时间顺序日志</section>
</li>
<li>
<section style="color: #010101;">输出是主题化长期记忆</section>
</li>
</ul>
<p data-tool="mdnice编辑器">session memory compact 处理的是「上下文窗口」问题。KAIROS dream 处理的是「长期事件沉淀」问题。这两类压缩混在一起看会非常乱，源码里其实已经把它们分得很开。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">10 小结</span></h2>
<p data-tool="mdnice编辑器">这套设计的工程代价与收益</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">10.1 一些值得学习的点</span></h2>
<p data-tool="mdnice编辑器">第一，分层彻底。长期记忆、当前轮召回、会话摘要、子代理记忆，各自有自己的存储形态和注入入口。系统复杂度是被隔离开的。</p>
<p data-tool="mdnice编辑器">第二，文件优先。排查方便，审计方便，人工纠错方便。很多团队高估了数据库和向量库的必要性，低估了可观察性的重要性。</p>
<p data-tool="mdnice编辑器">第三，动态召回走轻量 manifest + side query。对 CLI Agent 这种高频交互场景，这个方案的性价比很高。它把复杂度留给模型的小规模选择，而不是重型检索基础设施。</p>
<p data-tool="mdnice编辑器">第四，压缩时保 recent window，并修补 tool_use/tool_result 不变量。这一点极少有团队一开始就写对。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">10.2 一些代价</span></h2>
<p data-tool="mdnice编辑器">第一，frontmatter 的 <code style="color: #0e8aeb;">description</code> 质量变成关键依赖。这个字段一旦写烂，召回效果会大幅波动。它省掉了 embedding 的复杂度，也把一部分压力前置给写入质量。</p>
<p data-tool="mdnice编辑器">第二，双通道写入意味着状态机会更复杂。主模型可以写，后台 extractor 也能写。虽然代码里有跳过逻辑，但这类架构天然比单通道更需要小心。</p>
<p data-tool="mdnice编辑器">第三，session memory 的 section 截断是粗粒度的。它靠字符数近似 token，再按行截断，这属于保底工程，不属于精细压缩。能用，谈不上漂亮。</p>
<p data-tool="mdnice编辑器">第四，<code style="color: #0e8aeb;">MEMORY.md</code> 仍然有索引容量压力。即便动态召回已经分担了很大一部分负担，入口索引的组织质量依然重要。</p>
<h2 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">10.3 我们能用什么</span></h2>
<p data-tool="mdnice编辑器">如果把这套思路迁移到我们自己的 Agent 系统，可以借鉴（抄）：</p>
<p data-tool="mdnice编辑器">第一，先拆问题，再选技术。你要先决定自己在解哪件事：跨会话长期记忆、当前轮检索、超长对话压缩、团队共享经验。不要一上来就建一个统一 Memory API。</p>
<p data-tool="mdnice编辑器">第二，先用文件，再考虑数据库。只要你的系统规模还没逼到那个份上，文件系统几乎总是更划算。它便宜、透明、好调试。很多团队用数据库，是因为觉得那样「更像正经系统」，这个判断没什么含金量。</p>
<p data-tool="mdnice编辑器">第三，把召回质量的责任前移到写入阶段。Claude Code 用 <code style="color: #0e8aeb;">description</code> 做 manifest 检索这件事，给我的启发很大。与其指望后面靠复杂召回算法弥补，不如要求写入时就产出高质量摘要和类型信息。</p>
<p data-tool="mdnice编辑器">如果你们团队正在做本地化的企业内 Agent，我甚至建议先抄一版这种架构原型：<br />
长期记忆用 Markdown + frontmatter，当前轮召回走 manifest + 小模型筛选，会话压缩单独维护结构化 summary。三周内就能跑起来。比起一开始堆向量库、事件总线、关系数据库，这条路短得多。</p>
<h1 data-tool="mdnice编辑器"><span class="content" style="color: #0e8aeb;">11. 其它</span></h1>
<p data-tool="mdnice编辑器">Claude Code 的记忆系统没有神秘技术。它的难点不在某个单点算法，在边界控制和时机设计。什么时候写，写到哪里，什么时候读，读多少，压缩后保留什么，这些问题都比「用什么模型做召回」更重要。</p>
<p data-tool="mdnice编辑器">如果你把这篇文章里的结论压成一句工程建议，那就是：<br />
先把长期记忆、短期相关记忆、会话压缩拆开，再谈检索和存储。</p>
<p data-tool="mdnice编辑器">源码入口可以优先读这几组文件：</p>
<ul data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;">长期记忆规则与路径：<br />
[memdir.ts] [paths.ts] [memoryTypes.ts]</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">记忆静态注入与动态召回：<br />
[claudemd.ts] [attachments.ts] [findRelevantMemories.ts]</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">会话记忆与压缩：<br />
[sessionMemory.ts] [prompts.ts] [sessionMemoryCompact.ts]</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">团队共享记忆：<br />
[teamMemPaths.ts] [teamMemorySync/index.ts]</p>
</section>
</li>
</ul>
<p data-tool="mdnice编辑器">以上。</p>
</section>
</section>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/04/claude-code-source-memory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
