从 Pi 到 DSH:Agent Harness 如何从「可扩展」走向「自生长」

大模型能力持续提升之后,Agent 系统的竞争焦点正在发生变化。

过去,我们主要关心模型能不能理解任务、调用工具、编写代码。现在,更重要的问题逐渐变成:模型之外的系统,能否为 Agent 提供一个可以持续变化的运行环境?

这个运行环境通常被称为 Agent Harness

Harness 负责把模型、提示词、工具、记忆、上下文、权限和外部环境连接起来。它决定模型能够看到什么、调用什么、保存什么,以及一次行动会产生怎样的系统影响。

从这个角度看,Agent 的能力并不只来自模型,用一个公式来表达,大概如下:

Agent 能力
=
模型能力
× 上下文组织
× 工具系统
× 运行时结构
× 生命周期治理

如果 Harness 是固定的,那么即使模型越来越强,Agent 的能力边界仍然主要由开发者预先决定。

如果 Harness 可以扩展,用户和开发者就能不断为 Agent 增加工具、技能和工作流。

但如果我们希望 Agent 进一步具备「自生长」能力,仅仅提供扩展接口还不够。系统还必须允许 Agent:

  1. 发现自己的能力缺口;
  2. 生成或引入候选能力;
  3. 在运行时安全地激活这些能力;
  4. 验证变化是否有效;
  5. 在失败时完整回滚;
  6. 将成功经验沉淀为可复用组件;
  7. 淘汰已经失效或长期无用的能力。

Pi 与 DSH 可以被视为这条演进路径上的两个阶段。

Pi 回答的是:

如何构建一个足够小、足够开放,可以持续扩展的 Agent Harness?

DSH 进一步追问:

如何让 Agent 不只是使用外部提供的扩展,而是安全地参与自身能力结构的形成?

这不是从一种插件格式切换到另一种插件格式,而是 Agent Harness 从开放扩展平台能力生长环境的转变。

1. 什么是 Agent Harness

一个最简单的 Agent,可以被表示为:

Model
  ↓
Prompt
  ↓
Tool Call
  ↓
Environment

模型接收上下文,生成工具调用,再根据工具结果继续推理。

但在真实系统里,Agent 还需要处理更多问题:

  • 当前有哪些工具可用?
  • 工具由谁注册?
  • 不同任务应该使用什么模型?
  • 哪些信息应该进入上下文?
  • 哪些记忆需要跨会话保存?
  • 如何限制文件、网络和进程权限?
  • 工具调用失败后如何恢复?
  • 新能力如何加载?
  • 组件移除后如何清理副作用?
  • 不同组件之间的依赖如何表达?

于是,Agent 的实际结构更接近于:

                ┌─────────────┐
                │    Model    │
                └──────┬──────┘
                       │
                ┌──────▼──────┐
                │ Agent Loop  │
                └──────┬──────┘
                       │
       ┌───────────────┼────────────────┐
       │               │                │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│    Tools    │ │    Memory   │ │   Context   │
└─────────────┘ └─────────────┘ └─────────────┘
       │               │                │
       └───────────────┼────────────────┘
                       │
                ┌──────▼──────┐
                │ Environment │
                └─────────────┘

Harness 并不是模型外面的一层简单包装。

它实际上规定了 Agent 的:

  • 能力边界;
  • 行为边界;
  • 状态边界;
  • 权限边界;
  • 演化边界。

因此,当我们讨论 Agent 是否可以扩展、重构甚至自生长时,本质上讨论的不是模型参数如何变化,而是 Harness 能否安全地改变自身结构

2. Pi:以最小内核换取最大扩展空间

Pi 的核心思想非常明确:

不要预先替用户决定完整工作流,而是提供足够小的基础能力,让用户自己构建需要的 Harness。

Pi 将自己定义为一个最小化的 Agent Harness,并通过 Extensions、Skills、Prompt Templates、Themes 和 Packages 提供扩展能力。它允许用户修改工具、命令、模型提供商、工作流、上下文处理和终端界面,也支持将这些资源打包后通过 npm 或 Git 分发。(pi.dev)

这背后是一种「原语优先」的设计哲学:

不是:
内置所有功能

而是:
提供少量原语
+
开放扩展接口
+
允许用户自行组合

2.1 最小化不是能力不足

传统 Agent 产品通常倾向于内置更多功能:

  • 规划模式;
  • 子 Agent;
  • 权限确认;
  • MCP 集成;
  • 后台任务;
  • 长期记忆;
  • 沙箱;
  • Todo 系统。

Pi 选择了另一条路线:这些能力不一定需要成为内核的一部分,它们可以通过扩展或外部环境实现。

Pi 当前提供文件读取、文件修改、内容搜索和命令执行等内置工具,同时允许通过命令行配置工具集合,也允许 Extension 注册新的工具或覆盖现有工具。(pi.dev)

这种设计的意义把稳定的内核和变化的能力分开:

稳定部分:
模型调用、Agent Loop、会话、基础工具、扩展 API

变化部分:
工具、技能、上下文、工作流、权限策略、界面、模型路由

只要扩展接口足够开放,功能就不必全部固化在核心代码中。

2.2 Pi 的四类扩展资源

从 Harness 的角度看,Pi 的可扩展性主要体现在以下几个层面。

2.2.1 Extensions:改变运行时行为

Extension 是可以进入 Agent 运行时的代码模块。

它可以:

  • 注册工具和命令;
  • 监听工具调用;
  • 拦截或修改行为;
  • 改变上下文;
  • 切换模型;
  • 增加权限检查;
  • 实现自定义 UI;
  • 覆盖内置工具;
  • 连接外部系统。

因此,Extension 改变的不只是模型“知道什么”,还可以直接改变 Harness“如何运行”。

2.2.2 Skills:注入按需能力

Skill 更接近一种可复用的过程知识。

它可以告诉 Agent:

  • 在什么情况下使用某种方法;
  • 如何执行特定工作流;
  • 如何调用外部命令;
  • 如何处理某类项目;
  • 如何检查输出质量。

Pi 将 Skill 设计为按需加载的能力包,使 Agent 不必在每次会话开始时把所有知识都放进上下文。(pi.dev)

2.2.3 Prompt Templates:固化交互模式

Prompt Template 将常见任务封装成可复用提示词,例如:

  • 代码审查;
  • 架构分析;
  • 发布检查;
  • 测试生成;
  • 故障排查。

它改变的是任务入口和交互结构。

2.2.4 Packages:分发完整能力

Package 可以将 Extensions、Skills、Prompt Templates 和 Themes 组合起来,通过 npm、Git 或本地路径安装。Pi 还支持临时加载 Package,使组件只对当前运行生效。(github.com)

这使 Pi 不只是一个 Agent,也成为一个 Harness 能力分发平台:

Pi Package
├── Extensions
├── Skills
├── Prompts
└── Themes

2.3 Pi 的关键突破:Agent 可以参与修改 Harness

Pi 最值得关注的地方,不只是「插件多」。

它的官方描述明确鼓励用户让 Pi 编写自己需要的扩展,并在修改后通过重新加载继续当前工作。(pi.dev)

这意味着一种新的工作方式正在出现:

Agent 发现缺少某项能力
        ↓
Agent 编写 Extension
        ↓
用户检查或确认
        ↓
重新加载 Harness
        ↓
Agent 使用新增能力继续任务

过去,Agent 与开发工具之间的关系通常是:

人类开发 Harness
Agent 使用 Harness

在 Pi 中,它开始变成:

人类定义目标
Agent 修改 Harness
Agent 使用修改后的 Harness

这是从「可扩展」走向「自生长」的重要一步。

但是,这还不等于完整的自生长。

3. 行为自治不等于结构自治

理解 Pi 与 DSH 的关系,需要区分两种不同的自治。

3.1 行为自治

行为自治指 Agent 可以在已有能力范围内自主决定:

  • 下一步做什么;
  • 调用哪个工具;
  • 如何拆解任务;
  • 是否修改文件;
  • 是否运行测试;
  • 如何根据结果调整计划。

此时,Agent 的选择空间是动态的,但能力集合通常是预先确定的。

固定工具集合
    ↓
Agent 自主选择工具
    ↓
完成任务

3.2 结构自治

结构自治指 Agent 可以改变自己的能力结构:

  • 创建新工具;
  • 安装新组件;
  • 替换 Memory;
  • 修改上下文策略;
  • 调整模型 Router;
  • 增加权限规则;
  • 组合新的执行流程;
  • 卸载无效组件。
当前能力结构
    ↓
Agent 发现能力缺口
    ↓
生成候选组件
    ↓
改变 Harness
    ↓
形成新的能力结构

Pi 已经为结构自治打开了入口。

但它的扩展机制主要回答的是:

如何把一项新能力加入系统?

真正的自生长还必须回答:

  • 新能力应该在什么条件下激活?
  • 它依赖哪些已有能力?
  • 它失败后能否完整退出?
  • 它注册的工具和监听器由谁撤销?
  • 如何判断变化带来了正收益?
  • 如何防止不同扩展相互冲突?
  • 如何把一次临时变化沉淀成长期能力?
  • 如何淘汰不再适用的组件?

这些问题将我们从扩展系统带到了组件运行时。

4. DSH:为 Harness 自生长建立运行时基础

本文讨论的 DSH,不只是另一个插件系统。

它试图将 Agent Harness 表达为一个可以在运行中不断组合和重组的组件系统。

其基本结构可以概括为:

Component
=
Context
+
Effect
+
Cleanup
+
Coeffects

这四个概念分别回答四个问题:

概念 回答的问题
Context 组件可以看到和使用什么?
Effect 组件加入系统后会产生什么影响?
Cleanup 组件退出时如何撤销影响?
Coeffects 组件依赖哪些外部能力或其他组件?

DSH 的目标不是让所有模块都能任意修改系统,而是让变化成为一种显式、可追踪、可逆的运行时操作

4.1 Context:为能力提供明确边界

一个组件不能直接访问所有系统状态。

它应该通过 Context 获取所需能力,例如:

Context
├── Model Registry
├── Tool Registry
├── Memory
├── Event Bus
├── Session
├── Logger
├── Storage
├── Permission
└── Environment

Context 的第一层作用是解耦。

组件不需要知道某个能力的具体实现,只需要知道运行环境向它提供了什么。

例如,一个模型路由组件可能只依赖:

Model Registry
Task Metadata
Usage Metrics

一个长期记忆组件可能只依赖:

Session Events
Embedding Service
Storage
Context Injector

一个工具组件则可能只依赖:

Tool Registry
Credentials
Network
Logger

Context 的第二层作用是限制能力边界。

如果组件只能通过 Context 访问环境,那么系统就可以决定:

  • 哪些资源向它开放;
  • 哪些能力只读;
  • 哪些调用需要权限;
  • 哪些状态不能跨组件共享;
  • 哪些操作只能在 Sandbox 中执行。

因此,Context 不只是依赖注入,也是一种能力安全模型:

组件能做什么
≈
Context 向它暴露什么

4.2 Effect 与 Cleanup:让变化可以被撤销

当组件加入 Harness 时,通常会产生副作用。

例如:

  • 注册一个工具;
  • 添加一个事件监听器;
  • 打开数据库连接;
  • 启动后台任务;
  • 修改模型路由;
  • 向上下文注入内容;
  • 挂载文件目录;
  • 注册快捷键;
  • 创建缓存;
  • 改变权限策略。

这些变化可以统一理解为 Effect:

Component
    ↓
Effect
    ↓
Harness 状态发生变化

问题在于,大多数插件系统只强调如何创建 Effect,却没有把撤销 Effect 当作同等重要的能力。

于是,组件卸载后可能出现:

  • 工具仍然留在 Registry 中;
  • 事件监听器重复注册;
  • 后台任务继续运行;
  • 网络连接没有关闭;
  • 临时文件没有删除;
  • Context 中残留失效状态;
  • 新旧路由规则同时生效。

在 DSH 中,Effect 应该返回对应的 Cleanup:

Effect(Context) → Cleanup

例如:

function activate(context{
  const unregister = context.tools.register(myTool)

  return function cleanup() {
    unregister()
  }
}

更复杂的组件可能产生多个副作用:

function activate(context{
  const stopTool = registerTool(context)
  const stopListener = registerListener(context)
  const stopWorker = startWorker(context)
  const closeConnection = connectDatabase(context)

  return async function cleanup() {
    await stopWorker()
    stopListener()
    stopTool()
    await closeConnection()
  }
}

这使组件具备完整生命周期:

创建
  ↓
激活
  ↓
运行
  ↓
停用
  ↓
清理

4.3 时间可组合性:让 Agent 有资格试错

Effect 与 Cleanup 提供的是一种时间可组合性

一个组件可以在某个时刻进入系统,也可以在另一个时刻完整退出:

t₀:Harness 原始状态

t₁:组件进入
    → 注册工具
    → 启动服务
    → 注入上下文

t₂:组件运行

t₃:组件退出
    → 移除工具
    → 停止服务
    → 撤销上下文

t₄:Harness 恢复到可预测状态

这对普通插件系统很重要,但对自生长系统更重要。

因为自生长必然包含试错。

Agent 创建的新工具、新路由器、新记忆策略,不可能每次都正确。如果一次失败的尝试不能被完整撤销,那么每次实验都会向系统中留下残余状态。

最终,所谓“生长”就会退化成不可控的复杂度积累。

因此,自生长的基本过程不应该是:

生成组件
  ↓
永久安装

而应该是:

生成候选组件
      ↓
执行受控 Effect
      ↓
验证运行结果
   ┌──┴──┐
 成功    失败
  │       │
保留   Cleanup

Cleanup 的意义不只是“支持热卸载”。

它赋予 Agent 一种更关键的能力:

在不永久污染系统的前提下试验新的自身结构。

4.4 Coeffects:让依赖关系成为运行时的一部分

时间可组合性解决的是组件何时进入、何时退出。

但 Agent Harness 的组件并不是彼此孤立的。

如果依赖关系只是组件内部的隐式假设,运行时就无法回答:

  • 组件现在能否启动?
  • 它缺少什么能力?
  • 某个依赖消失后,哪些组件应该停用?
  • 替换一个 Provider 会影响哪些组件?
  • 哪些组件可以被安全卸载?
  • 一个候选组件是否与当前环境兼容?

Coeffects 用于显式表达组件所需的外部条件:

Effect:
组件对系统做什么

Coeffects:
组件需要系统提供什么

例如:

const vectorMemory = {
  coeffects: [
    "embedding-model",
    "vector-storage",
    "session-events"
  ],

  effect(context) {
    // 激活 Memory
    return cleanup
  }
}

运行时可以根据当前 Context 判断组件是否具备激活条件:

依赖全部满足
    ↓
组件激活

依赖不完整
    ↓
组件保持未激活

依赖运行中消失
    ↓
执行 Cleanup

这使 Harness 不再只是一个插件列表,而是一个动态依赖图:

Credential
    ↓
GitHub Provider
    ↓
GitHub Tool
    ↓
Repository Agent

或者:

Embedding Model ─┐
                 ├→ Vector Memory → Context Injector
Vector Storage ──┘

4.5 空间可组合性:让生长不是无序堆积

Coeffects 提供的是一种空间可组合性

组件不是按照固定顺序硬编码在系统中,而是根据能力和依赖形成运行时拓扑。

当一个能力出现时,依赖它的组件可以被激活;当这个能力消失时,相关组件可以被停用:

Sandbox 出现
    ↓
Code Executor 激活
    ↓
Test Runner 激活
    ↓
Coding Agent 获得安全执行能力

如果 Sandbox 被移除:

Sandbox 消失
    ↓
Code Executor Cleanup
    ↓
Test Runner Cleanup
    ↓
相关工具从 Agent 能力集合中撤销

这与传统插件系统有一个关键区别。

传统插件系统更像:

安装了什么
=
系统拥有什么

而动态组件运行时更像:

当前可用能力
=
当前组件
× 当前依赖
× 当前环境
× 当前权限

这使 Harness 的结构可以随着任务和环境变化,而不是不断向全局系统中永久添加模块。

真正的生长,不是组件数量持续增加,而是系统能够形成更适合当前任务的能力结构。

4.6 从动态重组到自生长闭环

Context、Effect、Cleanup 和 Coeffects 为动态重组提供了基础。

但必须强调:

动态重组是自生长的必要条件,不是自生长的全部。

完整的自生长至少需要五个阶段。

4.6.1 第一阶段:发现能力缺口

Agent 首先要判断自己缺少什么。

例如:

  • 当前没有访问某类数据的工具;
  • 现有 Tool 无法处理特定协议;
  • Memory 无法支持长期任务;
  • 当前模型不适合某类输入;
  • 缺少项目专用的验证流程;
  • 当前执行环境不满足安全要求;
  • 工具调用成本或延迟过高。

能力缺口不能只由「工具调用失败」判断。

它还可能来自:

  • 任务规划;
  • 运行指标;
  • 用户反馈;
  • 测试结果;
  • 历史失败记录;
  • 现有能力清单;
  • 环境变化。

因此,自生长的起点不是生成代码,而是:

目标要求
-
当前能力
=
能力缺口

4.6.2 第二阶段:生成或引入候选能力

识别缺口后,Agent 可以选择不同方式补齐能力:

  • 编写新的 Tool;
  • 生成新的 Skill;
  • 安装已有 Package;
  • 包装外部 API;
  • 组合已有组件;
  • 替换 Memory Provider;
  • 调整模型 Router;
  • 创建新的工作流;
  • 启动一个专用子 Agent;
  • 为现有组件增加适配层。

这里的关键词是「候选」。

Agent 生成的组件不能因为能够编译或加载,就自动成为系统的永久能力。

生成成功
≠
能力有效
≠
适合长期保留

4.6.3 第三阶段:在受控环境中激活

候选组件应该先进入受限 Context。

系统需要明确:

  • 它可以访问哪些目录;
  • 可以调用哪些网络服务;
  • 是否可以读取凭证;
  • 可以注册哪些工具;
  • 能否修改全局状态;
  • 资源消耗上限是多少;
  • 运行时间是否受限;
  • 哪些副作用必须登记。

这一点尤其重要,因为扩展代码通常拥有较高权限。

以 Pi 为例,其官方安全文档明确说明,内置工具和 Extension 默认继承启动 Pi 的进程权限;第三方 Package 可能执行代码或指示模型执行操作,因此需要代码审查,并在需要时依赖容器或虚拟化提供真正的隔离边界。(github.com)

如果 Agent 开始自行生成和加载组件,权限问题只会更加突出。

所以,自生长必须建立在受控运行时上,而不能建立在「默认信任所有新代码」之上。

4.6.4 第四阶段:验证、保留或回滚

候选能力激活后,系统需要对它进行验证。

验证可以包括:

  • 能否完成目标任务;
  • 是否通过单元测试;
  • 是否破坏已有功能;
  • 是否产生未声明的副作用;
  • 是否扩大了不必要的权限;
  • 是否降低了任务成本;
  • 是否提高了成功率;
  • 是否造成明显的上下文膨胀;
  • 是否与现有组件冲突;
  • Cleanup 是否完整。

验证结果通常有三种:

验证通过
    ↓
保留或固化

部分通过
    ↓
修改后重新试验

验证失败
    ↓
Cleanup + 回滚

因此,自生长不是一次性的代码生成,而是一个选择过程:

Generate
→ Activate
→ Observe
→ Evaluate
→ Select

没有评估的生成,只是变化。

经过评估和选择的变化,才可能成为生长。

4.6.5 第五阶段:沉淀、复用与淘汰

一次任务中的成功,不代表组件值得永久保留。

系统还需要决定:

  • 这项能力是否跨会话有效?
  • 它适用于哪些任务?
  • 应该在什么条件下重新激活?
  • 它依赖哪些版本?
  • 它的权限范围是什么?
  • 它由谁生成?
  • 经过了哪些测试?
  • 是否允许自动升级?
  • 何时应该重新评估?
  • 何时应该被淘汰?

因此,一个可复用组件除了代码,还需要附带元数据:

Component
├── Implementation
├── Capability Description
├── Coeffects
├── Permissions
├── Validation Records
├── Version
├── Provenance
├── Metrics
├── Effect
└── Cleanup

真正的自生长闭环应当是:

发现缺口
  ↓
生成候选能力
  ↓
隔离激活
  ↓
观察与验证
  ↓
保留或回滚
  ↓
沉淀为可复用组件
  ↓
持续评估
  ↓
升级或淘汰

5. Pi 与 DSH 的核心差异

Pi 与 DSH 并不是简单的替代关系。

它们关注的是两个不同层次的问题。

维度 Pi DSH
核心目标 构建开放、可定制的 Agent Harness 构建支持动态变化的组件运行时
能力来源 Extensions、Skills、Prompts、Packages 运行时组件及其依赖关系
主要变化发起者 用户、开发者,也可以由 Agent 辅助 用户、系统或 Agent
组件组织方式 扩展资源与 Package 动态依赖图
激活方式 启动加载、临时加载或重新加载 根据 Context 与 Coeffects 激活
生命周期 以扩展加载和配置为中心 Effect 与 Cleanup 对称管理
依赖治理 主要由扩展代码和包依赖处理 将运行时能力依赖显式化
失败处理 依赖扩展实现、进程或会话边界 通过 Cleanup 支持组件级回滚
演化方向 从固定产品走向开放平台 从开放平台走向受控自生长
核心价值 让 Harness 容易被改变 让 Harness 可以安全地持续改变

可以把两者的关系概括为:

Pi:
稳定核心
+
开放扩展点
+
能力分发机制

DSH:
组件化 Context
+
显式 Coeffects
+
可逆 Effect
+
动态生命周期

Pi 解决了「能力能否加入」的问题。

DSH 更关注「能力如何进入、如何协作、如何退出,以及如何在运行时形成新的结构」。

6. 从可扩展到自生长,中间还差什么

可以把 Agent Harness 的演进分为三个阶段。

6.1 第一阶段:固定能力

模型
+
固定提示词
+
固定工具

系统能够执行任务,但能力边界在设计阶段已经确定。

如果缺少能力,只能由开发者修改产品代码并重新发布。

6.2 第二阶段:开放扩展

稳定核心
+
Extensions
+
Skills
+
Packages
+
开放 API

用户和开发者可以持续增加能力。

Agent 也可以帮助编写扩展,但扩展的发现、安装、验证和维护通常仍然依赖人工流程。

Pi 代表了这一阶段的重要方向:Harness 不再是一个封闭产品,而成为可以根据个人工作流持续定制的平台。

6.3 第三阶段:受控自生长

稳定内核
+
能力缺口识别
+
候选组件生成
+
动态组件运行时
+
显式依赖
+
可逆副作用
+
隔离验证
+
自动回滚
+
能力沉淀
+
持续淘汰

Agent 不再只是等待外部为它安装能力。

它可以根据任务识别不足,提出新的能力结构,在受控环境中试验,并根据结果决定保留、修改还是撤销。

这时,Agent 的角色从能力消费者变成了能力形成过程的参与者。

7. 自生长不等于无限增长

「自生长」并不是 Agent 不断为自己增加工具和代码。

无限增加不是生长,而是熵增。

一个只会添加能力、不会清理能力的系统,最终会出现:

  • 工具数量不断膨胀;
  • 相似能力重复实现;
  • 组件版本相互冲突;
  • 权限范围持续扩大;
  • 上下文被大量描述占据;
  • 路由规则越来越难以理解;
  • 无效监听器和后台任务持续运行;
  • Agent 无法判断应该使用哪个工具;
  • 系统行为逐渐不可预测。

因此,自生长必须同时包含四种能力:

增加
+
选择
+
清理
+
遗忘

可以进一步表示为:

可持续生长
=
生成新能力
-
淘汰无效能力
+
重组已有能力

这也是 Cleanup 和生命周期管理的重要性所在。

真正成熟的 Agent 不仅要知道「我还需要什么」,还要知道:

  • 什么已经不需要了;
  • 什么正在产生负面影响;
  • 什么应该暂时停用;
  • 什么可以被更简单的组件替代;
  • 什么经验只适用于过去的环境。

遗忘不是生长的反面。

受控遗忘本身就是生长的一部分。

9. Pi 与 DSH 不是替代,而是演进

Pi 的价值在于证明了一件事:

Agent Harness 不需要是一个功能固定的封闭产品。

通过开放 Extension、Skill、Prompt 和 Package,Harness 可以被用户重新塑造,也可以让 Agent 辅助编写自身需要的扩展。

这已经比传统 Agent 产品向前迈出了一大步。

DSH 所代表的方向,则是在此基础上进一步抽象:

如果 Agent 可以创建新能力,那么这些新能力应该如何成为运行时的一等公民?

答案不能只是把更多代码放进扩展目录。

系统还需要:

  • 明确组件所处的 Context;
  • 显式声明组件依赖的 Coeffects;
  • 管理组件产生的 Effect;
  • 在组件退出时执行 Cleanup;
  • 根据环境变化重新计算能力拓扑;
  • 对候选能力进行验证;
  • 将有效能力沉淀下来;
  • 将失效能力安全淘汰。

因此,二者可以形成一种递进关系:

Pi:
让 Harness 可以被修改

        ↓

DSH:
让修改具有显式生命周期

        ↓

自生长 Agent:
让 Agent 可以发起、验证并沉淀修改

从这个角度看,DSH 不是对 Pi 的否定。

它是在 Pi 所代表的开放扩展思路上,将“变化”进一步提升为运行时的核心抽象。

10. Harness 正在成为 Agent 的生长环境

如果说 Pi 的核心贡献,是把 Agent 从一个封闭产品变成一个可编程、可扩展的平台,那么 DSH 所探索的下一步,就是让 Agent 逐渐成为自身能力变化的参与者。

它不只是使用已有工具,还可以:

  • 发现能力缺口;
  • 创建候选组件;
  • 调整能力组合;
  • 在受控环境中试验;
  • 根据结果保留或回滚;
  • 将成功经验沉淀为长期能力。

但自生长不等于无限增加。

一个只会安装新工具、写入新记忆、叠加新策略的 Agent,最终只会被自己积累的复杂度拖垮。

真正可持续的生长,必须同时包含:

发现
→ 生成
→ 激活
→ 验证
→ 选择
→ 清理
→ 沉淀
→ 淘汰

Pi 回答了:

如何让 Agent Harness 可以被持续扩展?

DSH 则进一步追问:

如何让 Agent 安全地参与自身能力的形成?

从 Pi 到 DSH,变化的不只是扩展机制,而是 Harness 的角色。

它正在从承载工具与插件的工程框架,转变为支持能力试验、筛选、重组和沉淀的运行环境。

未来的 Agent Harness 可能不再只是模型与工具之间的连接层。

它还将成为 Agent 管理自身变化的基础设施:

  • 允许新能力出现;
  • 阻止错误变化扩散;
  • 保存经过验证的经验;
  • 清除已经失效的结构;
  • 在保持稳定内核的同时持续重组外围能力。

只有当 Agent 既能增加能力,也能验证、回滚、清理和遗忘时,它才真正具备从「可扩展的软件」走向「可持续生长的系统」的可能。

以上。

历史总是在重演,AI 时代的我们应该做些什么

很多公司以为自己接入了几个大模型,采购了一批智能体工具,员工就获得了某种近乎无限的生产力。

换个角度看:每个人突然多出了一百万名能力不稳定、缺乏上下文、不会主动澄清目标、偶尔虚构进度、还能高速消耗预算的下属。

这些下属不需要工位,也不会请假。它们一天可以提交上千次结果,看起来永远在工作。管理者很容易被这种吞吐量迷惑,误把生成速度当成有效产出,误把调用次数当成自动化程度,误把一段流畅的回答当成任务已经完成。

AI 把执行成本压得很低,同时把管理问题放大了。

今天的智能体系统可以被看成一种新型组织。模型是员工,token 是人力预算,上下文是岗前培训,工具权限是组织授权,工作流是汇报关系,评估体系是绩效制度,人工验收则对应管理责任。

按照这个视角观察,很多 AI 项目的失败也是情里之中。它们把模型能力当成唯一变量,却没有建立与之配套的管理系统。结果类似一家突然扩张到百万人的公司:招聘极快,职责模糊,没有培训,没有绩效标准,管理者还希望它自行涌现出秩序。

历史上,这类问题出现过。

铁路旧事

十九世纪三十年代的铁路热潮带来了前所未有的运输能力。铁路解决了距离和速度问题,也制造了规模、调度、协作和安全问题。

单条铁路容易运营。线路变长、车次增加、岗位分化以后,系统复杂度迅速上升。信息必须跨地区传递,车辆必须统一调度,责任必须分层,事故必须被记录和复盘。原有的管理方式无法支撑新基础设施的吞吐量,事故随之发生。

铁路公司最终补上的,是现代管理体系。

技术增加了系统能力,管理制度把能力组织成可持续的产出。铁路后来成为第一个十亿美元产业,支撑它的并非轨道和机车本身,还包括围绕大规模协作建立的组织结构。

AI 正在重演类似的路径。

过去的软件系统严格服从预定义逻辑。输入符合条件,程序进入对应分支。工程团队可以通过代码结构、类型系统、测试和运行指标逐层收紧系统行为。

智能体的行为边界宽得多。它可以搜索、分析、生成、调用工具、保存记忆、继续拆解任务。它也可能误解任务、忽略约束、重复调用、把猜测写成事实,在结果看似完整时掩盖中间步骤的错误。

当模型调用规模扩大,问题便从「它会不会回答」变成「我们怎样管理一支由概率模型构成的劳动力」。

许多企业仍在用采购软件的思路处理这件事:买更强的模型,开放更多上下文,增加 token 预算,再连接更多工具。

这很容易走向失控。

人海复现

遇到复杂任务就增加 token,和过去遇到项目延期就增加人手,逻辑高度相似。

管理者看到结果不好,第一反应往往是扩大上下文窗口,让智能体多思考几轮,再增加几个子智能体并行搜索。系统图越来越复杂,调用链越来越长,账单同步上涨。

问题可能出在任务定义上。

一个智能体收到「分析这家公司是否值得投资」,它需要自行猜测分析期限、风险偏好、数据范围、估值框架和输出用途。另一个智能体收到「优化系统性能」,它也要猜瓶颈位于吞吐量、尾延迟、内存占用、启动时间还是硬件成本。

人类员工面对这种指令,会追问。智能体更可能直接开始工作。它会用流畅语言填补任务中的空白,把未经确认的假设埋入推理过程,最终交付一份结构完整、目标偏离的结果。

给它更多 token,只会让偏离过程更长。

这和组织扩张中的人海战术没有本质差异。需求尚未稳定时增加开发人员,沟通路径随人数增长,信息损耗也随之增长。新增人员首先要理解问题,再理解已有方案,然后处理方案之间的冲突。最后,大量时间花在协调新增人力本身。

多智能体系统也会出现同样的问题。

一个规划智能体拆任务,多个执行智能体并行处理,汇总智能体负责合并,审查智能体再做验证。架构图确实很漂亮。但实际运行时,规划阶段的歧义被复制到所有分支,各个执行智能体基于不同假设工作,汇总阶段只能用更多 token 消解冲突。

最终系统花费大量计算资源,证明自己已经花费了大量计算资源。

智能体反复自我调用的循环尤其典型。表面上看,它在持续反思和改进;深入观察调用轨迹,常常会发现它没有获得新的外部信息,也没有引入新的判定标准,只是在几个近似答案之间改写措辞。

这种循环不会自然收敛。缺少验收条件时,「继续思考」没有终点。

工程上必须为循环设置退出规则:哪些指标达到后停止,连续多少轮没有新增信息后停止,成本超过多少后转人工,发生哪些工具错误后禁止重试。退出规则缺失,智能体就会把预算消耗当成工作进展。

上下文债务

几乎没人会给 AI 恰当的语境。

这句话听起来像提示词问题,实际涉及企业知识怎样存在、怎样更新、怎样被验证。

当一个人在公司里工作几年,会形成大量隐性知识。他知道某个字段名与实际含义不同,知道某项流程在文档里有三步、落地时有七步,知道某个客户的特殊约定,知道哪些数据能够使用,哪些结论虽然算得出来却不能直接发布。

这些知识分散在人的记忆、聊天记录、会议结论、历史工单和代码注释中。公司过去可以容忍这种状态,因为熟练员工承担了知识路由器的角色。谁遇到问题,找对人问一句即可。

AI 无法稳定获取这种语境。

把所有资料塞进上下文也解决不了。上下文越长,噪声越多;资料之间可能相互冲突;旧制度和新制度可能同时出现;局部例外可能被模型理解成通用规则。检索系统可以减少输入量,却无法自动判断哪份知识具备权威性。

上下文工程因此要处理四类问题。

第一类是范围。智能体完成当前任务究竟需要哪些信息,哪些材料只会分散注意力。范围太窄会漏掉约束,范围太宽会增加延迟和成本,也会提高错误引用的概率。

第二类是时效。文档必须带有版本、适用日期和失效条件。缺少这些元数据,模型很难区分现行规则与历史记录。

第三类是权威级别。制度文件、团队约定、个人经验和历史案例不能拥有相同权重。检索结果需要体现来源优先级,冲突时还要触发澄清或人工审批。

第四类是任务绑定。知识必须与执行步骤建立关系。把二十份文档交给智能体,让它自行判断何时使用,等于把一摞制度放到新员工桌上,然后要求他当天独立处理高风险业务。

上下文管理本身就是管理工作。它对应人类组织中的培训、制度建设和岗位说明。

企业在这里还会遇到政治阻力。

熟练员工掌握的独门知识,往往构成他在组织中的议价能力。让他把这些知识结构化地交给 AI,等于要求他亲手降低自身稀缺性。员工可能口头支持,实际只提交表层流程;关键判断仍保留在脑中,文档写得正确却无法操作。

靠宣传无法解决这种冲突。

知识沉淀必须进入正式职责,并与岗位价值重新绑定。贡献高质量规则、案例和评估集的人,需要获得与业务产出相当的认可。否则,组织一边要求员工共享知识,一边继续按照「不可替代程度」奖励个人,制度会驱动所有人保留信息。

AI 转型推进到深处,技术阻力通常会下降,组织阻力会持续上升。

冗员变形

传统组织里的冗员不一定完全不工作。他可能参加会议、整理材料、同步状态、反复确认,把时间消耗在缺少业务增量的活动上。

智能体也能制造同类繁忙。

大量 token 用于复述任务、生成计划、解释已经执行的步骤、重写已有答案。输出篇幅持续增长,新增信息却接近于零。调用记录看起来很丰富,真正影响最终决策的内容只占很小一部分。

「八成 token 什么都没做」虽然带有夸张色彩,却很接近许多智能体工作流的结构性问题。

衡量 token 效率不能只看输入输出数量。更合适的单位是有效决策增量:一次调用是否增加了新证据,是否排除了一个错误方向,是否完成了可验证的执行动作,是否降低了后续人工判断成本。

如果一轮调用没有完成以上任何一项,它大概率属于计算冗员。

企业很容易用平均调用成本掩盖这个问题。单次模型调用足够便宜时,团队会觉得多跑几轮无所谓。规模扩大后,浪费会在三个方向累积:直接推理成本、任务延迟,以及人工审查负担。

第三项经常被忽略。

智能体每多生成一份结果,人就多承担一份潜在验收工作。机器吞吐量可以在短时间扩大几十倍,人的审查能力没有同步扩张。最终形成新的队列:模型输出堆积,员工随机抽查,错误在未被发现的情况下进入下游。

这时再增加智能体,只会继续扩大待验收库存。

需要被放大的,是能够显著改变结果的「100 倍 token」。某次调用拿到了决定性证据,识别了关键矛盾,修正了任务边界,或者发现了会导致整条工作流失败的风险。这类调用数量很少,贡献却远高于普通生成。

寻找它们依赖调用追踪和结果归因。

每个工作流至少要记录:调用目的、输入来源、使用工具、产生的新信息、对最终结果的影响、失败类型以及人工修改位置。没有这套记录,团队只能看到账单和最终文本,无法分辨哪些调用有效,哪些调用只是增加长度。

这类似分析一个大型团队。只看员工人数和工作时长,无法判断组织效率。必须知道关键决策在哪里发生,哪些岗位形成瓶颈,哪些汇报关系制造重复劳动。

评估先行

管理智能体最有效的抓手是评估标准,也就是 evals。

编程成为 AI 当前最成功的应用场景,与代码天然具备可评估性有很大关系。程序可以编译或运行,测试可以通过或失败,性能可以测量,回归可以复现。模型生成的内容即使风格不同,也能被放入相对稳定的验证框架。

大量业务任务没有这种便利。

「研究一家企业」怎样算完成?

「生成高质量销售线索」中的高质量由谁定义?

「完成合同审查」需要发现哪些类型的风险?

「总结客户需求」允许遗漏哪些内容,又绝不能遗漏哪些内容?

企业如果不能回答这些问题,智能体也无法稳定交付。

很多团队先建设工作流,最后才补评估。他们把模型、检索、工具调用和记忆系统连接起来,跑出一批结果,然后组织专家凭感觉打分。几个版本之后,专家标准发生变化,历史结果无法比较,模型优化也失去方向。

评估应该早于大规模自动化。

任务进入智能体系统之前,先定义成功条件、失败类型和风险边界。评估集需要覆盖常规案例、边界案例、冲突信息、缺失信息以及必须拒绝处理的情况。只有理想样本的评估集,会把系统训练成演示环境里的优秀员工。

一个可用的评估体系至少分成四层。

第一层检查任务完成度。要求提取的字段是否齐全,要求执行的动作是否发生,输出格式是否符合下游接口。

第二层检查事实和证据。结论能否追溯到输入材料,引用是否支持对应判断,模型有没有用常识填补数据缺口。

第三层检查业务质量。结果是否符合领域规则,是否覆盖关键风险,是否达到能够进入下一流程的标准。

第四层检查运行效率。完成任务使用了多少 token、多少工具调用、多少时间,发生了多少次重试,人工修改比例是多少。

只评结果质量,系统可能通过十倍成本换取一点点效果提升。只评成本,系统又会通过减少分析步骤制造隐蔽错误。质量、成本和风险必须放在同一套评估里。

评估标准也不能永久固定。业务规则会变化,模型行为会变化,工具返回的数据结构也会变化。每次线上事故都应转化成新的评估案例。没有进入评估集的事故,后续很可能以相似形式再次出现。

这与人类团队的管理方式一致。OKR、质量标准、事故复盘和晋升要求,共同塑造员工行为。只给方向、不定义验收,最后只能依赖主管逐项盯人。

智能体同样需要制度化约束。

思想主权

AI 编程带来的另一个变化,是程序员的工作重心开始从逐行控制代码迁移到控制软件背后的想法。

模型一天能够生成数千行代码。开发者逐行审查全部输出,时间上已经不可行。即使坚持审完,也容易陷入局部细节:命名是否顺眼,函数是否拆得足够小,某段逻辑是否符合个人风格。

这些问题仍有价值,只是优先级下降了。

大模型擅长局部实现。给出清晰边界后,它可以完成函数、接口和测试,也能按照反馈快速调整。它对整体设计的把握更不稳定,尤其容易在多个局部合理选择之间拼出一个整体失衡的系统。

程序员必须控制设计意图。

数据结构为什么这样选择,状态由谁拥有,哪些不变量必须维持,失败后怎样恢复,性能目标是什么,哪些路径允许降级,哪些行为属于系统禁区。这些内容如果只存在于开发者脑中,AI 会用自己的概率偏好填补空白。

结果可能能运行,也可能通过局部测试,却难以演进。

控制思想要求开发者拥有足够深的系统理解。他需要判断某种设计会怎样影响内存布局、并发行为、故障边界和长期维护成本。只会写提示词无法完成这项工作。

vibe coding 最大的问题不在生成速度,而在责任链断裂。使用者描述一个模糊目标,模型生成实现,程序恰好能够运行,于是产物被视为完成。系统内部怎样工作、错误会在哪里积累、性能上限由什么决定,没有人掌控。

这种开发方式可以用于低风险原型。进入长期维护或高性能系统后,代价会快速暴露。需求变化一次,开发者无法判断应该修改哪一层;性能下降时,也不知道问题来自算法、数据结构还是调用关系。每次修改只能继续依赖模型猜测,系统逐步变成无人理解的代码堆积。

antirez 在开发本地 LLM 推理软件 DwarfStar 时,面对的是大量细微且会累积的错误。这类项目不能只看单个函数是否合理。一个局部误差、一处内存选择、一个数据结构上的偏差,都可能沿执行路径放大。

AI 在严谨设计和测试中可以提供很大帮助。前提是人掌握系统意图,知道该要求 AI 验证什么,也知道哪些结果不能接受。

代码审查也需要重新分配精力。

对于 Redis 这类大量用户会直接阅读和修改源码的项目,保持代码质量是对用户的尊重。审查仍然有意义。但如果开发者把全部时间用在检查每一行 AI 输出,QA、性能分析和下一步设计就会被挤压。

有限的人力应该优先投入故障模式、系统不变量、边界条件、性能退化和可维护性。代码风格可以交给自动化工具,重复性实现可以交给模型,局部错误可以由测试覆盖。设计责任无法外包。

设计文档

DESIGN.md 在 AI 编程环境中的地位会持续上升。

过去很多设计文档写于项目启动阶段,代码落地后很快过期。开发者最终以代码为准,文档只保留历史价值。AI 参与开发后,设计文档需要变成持续维护的系统接口。

它应该描述每个数据结构承担什么职责,关键实现技巧服务于什么目标,模块之间怎样协作,哪些不变量不能破坏,以及修改某部分时需要同步检查哪些路径。

模型阅读这样的文档,才能在修改代码前获取设计约束。当我们接手项目时,也可以先理解系统思想,再进入具体实现。

这并不意味着文档越长越好。把代码换成自然语言复述,价值很低。有效文档集中解释代码无法自行表达的内容:为什么选择这个方案,放弃了哪些方案,哪些行为依赖隐含前提,哪些性能特征必须保持。

文档还要进入变更流程。

如果代码改动影响数据结构、状态模型或失败处理,设计文档必须同步更新。评审时需要检查实现与文档是否一致。否则,AI 会依据旧设计修改新代码,错误会披着「遵循项目规范」的外衣进入系统。

设计文档可以视为给未来开发者和未来智能体准备的上下文。它承担组织记忆,减少关键思想只存在于少数人脑中的风险。

企业业务流程也需要同类文档。

流程说明不能停留在步骤列表。它要写清每一步的目标、输入、输出、判断依据、异常路径、升级条件和验收标准。只有这样,智能体才有可能承担稳定执行。

很多所谓 AI 落地难题,本质上暴露了企业从未把业务讲清楚。过去依赖熟练员工临场判断,这些模糊地带被人的经验掩盖。模型进入流程后,所有未定义部分同时暴露出来。

AI 没有制造这些混乱。它提高了混乱被复制的速度。

人的边界

AI 可以承担高吞吐的搜索、执行、分析和记忆管理。

搜索适合机器,因为它能在大量材料中并行查找候选信息;执行适合机器,因为重复流程可以被稳定调用;分析可以由机器生成多个假设和比较维度;记忆管理则可以通过检索、归档和关联降低人脑负担。

人需要保留四项责任:问题定义、歧义处理、风险判断和最终验收。

问题定义决定系统优化什么。目标写错,后续所有高效执行都会扩大偏差。

歧义处理决定何时允许模型自行推断,何时必须暂停并提问。完全禁止推断会让工作流频繁中断,完全开放推断又会把隐含假设带入结果。工程上应根据风险分级:低风险、可逆操作可以允许模型补全;高风险、不可逆操作必须要求显式确认。

风险判断需要结合业务后果。模型可以列出风险,却无法替组织承担责任。同样的错误,在内部草稿里可能只需重新生成,在合同、资金、生产系统和对外承诺中,影响完全不同。

最终验收意味着人要对结果负责。验收不能退化成快速扫一眼。模型输出量超过人的审查能力时,系统应限制吞吐量、增加自动评估或降低自动化范围。堆积大量无人验收的输出,没有形成生产力,只是形成了信息库存。

人机分工也不应按照「模型能做什么」设计。这个问题会随着模型升级不断变化。更稳定的划分方式是看责任和可验证性。

可验证、可回滚、低风险的任务,可以给智能体更大自治权。

结果可验证但动作难以回滚时,应增加审批点。

结果难以完整验证、错误影响又高的任务,AI 更适合作为分析和建议工具。

这套边界需要写进系统权限。只靠提示词要求模型谨慎,约束强度远远不够。工具层要限制可调用范围,工作流层要设置审批,运行层要保留审计记录,评估层要持续检查越权行为。

提示词属于沟通机制。权限系统才承担治理责任。

年轻工程师

我对年轻程序员是有些担心的,并非担心他们使用 AI,而是他们在建立心智模型之前就把实现过程全部交给 AI。

一个人没有亲手实现过解释器、数据库或哈希表,很难判断模型生成的实现在哪些地方存在结构性问题。他可能读得懂语法,也能运行测试,但无法推演数据怎样流动、状态怎样变化、性能为什么退化。

核对 AI 输出不能替代基础训练。

逐行检查一段自己并不理解的代码,只会制造虚假的参与感。更有效的训练方式是亲手实现规模受控的系统,遇到内存、并发、解析、索引和错误恢复问题,再用 AI 帮助验证思路、补充测试、寻找遗漏。

基础能力的价值还会上升。

代码生成越来越便宜以后,企业不会继续为普通代码行支付高溢价。能够定义系统、识别风险、设计评估、分析性能和承担技术决策的人,会掌握更大的杠杆。

年轻工程师如果只学习怎样让模型快速产出,能力会紧贴当前工具。模型更新一次,原有技巧可能迅速贬值。数据结构、操作系统、网络、数据库和编程语言建立的心智模型变化慢得多,它们决定一个人能否判断 AI 给出的方案。

高级工程师也不能因此停留在旧习惯里。

坚持所有代码都必须人工逐行编写,会把大量时间消耗在机器已经可以低成本完成的工作上。经验应该投入架构、约束、验证和复杂问题拆解。继续用代码行数证明专业性,和管理者用团队人数证明影响力没有太大差别。

管理重构

企业引入 AI 时,组织结构也要调整。

过去,一个经理管理十几个人已经接近沟通上限。未来,每个员工都可能拥有大量智能体。管理对象数量突然扩张,个人需要具备过去只有管理者才需要的能力:拆解任务、定义结果、提供上下文、设置检查点和处理异常。

工程师会越来越像技术经理。经理则需要理解评估、权限、成本和模型行为,单靠资源协调很难管理智能体劳动力。

团队流程也会变化。

需求评审需要增加可评估性检查。一个需求如果无法写出验收条件,进入智能体工作流后只会制造更多不确定输出。

架构评审需要关注智能体权限、上下文来源和失败路径。模型调用成功不等于业务任务成功,工具返回正常也不等于动作合理。

上线评审需要检查成本上限和停止条件。任何允许递归、自我调用或动态扩展任务的系统,都必须有预算约束。

事故复盘需要分析模型为什么做出对应行为,输入中缺少了什么,评估为什么没有拦截,以及权限设计是否允许错误继续扩大。把问题归结为「模型偶尔会犯错」,相当于铁路事故后只说机车存在风险。

采购更强的模型可能提升基线能力,却不会补齐管理缺口。模型越强,执行范围越大,错误的影响半径也越大。

AI 项目的成熟度最终会体现在几个问题上:

  1. 团队能否精确描述智能体负责的任务?
  2. 能否量化什么叫完成?
  3. 能否追溯结论来自哪些输入?
  4. 能否限制循环、重试和预算?
  5. 能否知道哪些 token 改变了结果?
  6. 能否在高风险动作前强制人工介入?
  7. 能否把线上失败转化成评估案例?
  8. 能否让设计思想脱离个人记忆,进入可维护的组织资产?

这些问题回答不出来,再复杂的智能体架构也只是一次昂贵的演示。

铁路时代的企业最终学会了管理速度、规模和复杂性。AI 时代需要处理的是概率行为、无限执行能力和有限人类判断之间的冲突。

我们已经拥有了数量近乎无限的数字员工。它们勤奋、便宜、速度极快,也缺少组织记忆、责任意识和稳定判断。

接下来的工作落在人身上:把问题讲清楚,把标准写出来,把权限收紧,把思想保存下来,对最后的结果签字。

这些都是基于当前模型能力和个人认知所作出的判断,随着时间的推移,也可能会涌现其它我当前所认知不到的,那又将是另一个世界。

以上。

使用 Vibe Coding 的这6 种后遗症,你有吗?

我已经很久没有沉浸式写代码了。

以前碰到一个复杂问题,我会花几个小时读调用链、画状态变化、跟踪异常路径。刚开始很慢,脑子里只有一些零散信息。随着上下文逐渐完整,代码会形成一张连续的结构图。再往后写,很多判断不需要反复查找,心流也就出现了。

现在的工作节奏完全变了。

我先给 Agent 描述需求,等它执行。等待期间又觉得空着可惜,于是打开第二个窗口,让另一个 Agent 补测试。看到还有时间,再开第三个任务处理重构。

十几分钟后,几个 Agent 陆续返回结果。我开始查看摘要、检查 diff、运行测试、补充要求、处理冲突。一个任务还没看完,另一个任务已经弹出完成通知。

一天下来,代码生成了很多,我却很少在同一个问题里连续停留半小时。

心流没了

Vibe Coding 最先改变的是注意力结构。

写代码原本是一种连续活动。理解需求、寻找入口、建立模型、设计实现、发现问题、修正判断,这些环节彼此相连。Agent 把它切成了很多轮对话:描述任务,等待结果,检查结果,再描述下一步。

每轮都很快,每轮都带来一点进度。

大脑很容易适应这种高频反馈。问题一旦需要长时间推演,我就会产生阻力。以前遇到难点,会继续读代码、查日志、进调试器。现在的第一反应经常是把问题发给 Agent,让它先分析一下。

思考开始变得外包化。

这不会让工程师立刻失去能力。更常见的变化是耐心下降。看十分钟调用链就想问 AI,调试几次没有结果就想换提示词,设计还没收敛就开始生成代码。

慢思考越来越难维持。

复杂工程问题偏偏依赖这种能力。并发状态、数据一致性、故障恢复和性能瓶颈,很少能靠几轮快速问答解决。它们需要人在同一套上下文里待得足够久,直到各种局部信息连成一体。

Agent 使用频率越高,我越忙,也越难进入这种状态。

Token 焦虑

额度快用完会焦虑,这很正常。额度没用完也会焦虑,就就有点奇怪了。

买了订阅,看到 token 还剩很多,会产生一种浪费感。离开工位之前,总想再布置一个任务。准备去开会,让 Agent 先跑一轮测试;准备吃饭,让它顺手整理模块;睡觉之前更容易上头,总觉得应该给 AI 加个通宵夜班。

真的是如群友所说:床前 token 光。

这种焦虑会慢慢改变任务优先级。原本没有必要立即处理的工作,因为 Agent 正好空闲,被提前塞进了队列。需求还没有想清楚,先做一个版本看看;某段代码虽然还能维护,先让 Agent 重构一下;测试已经够用,再补几十个用例似乎也没坏处。

Agent 忙起来了,人的待验收任务也堆起来了。

第二天早上打开电脑,几个任务全部显示完成。看起来像是白捡了一夜生产力。仔细检查才会发现,每个结果都需要重新加载上下文,都要判断实现边界,还要验证它有没有把局部问题扩展成新的抽象。

AI 上完夜班,我们开始加班验收。

更麻烦的是,等待结果本身也会占据注意力。人已经离开电脑,脑子里还惦记着任务有没有跑完、会不会失败、明天要看多少改动。休息时间变成了一段漫长的异步等待。

越用越累

刚开始用 Vibe Coding,我以为自己会轻松很多。实际体验是产出提高以后,疲惫感也跟着上升。

过去一天写两百行关键代码,我基本知道每一行为什么存在。现在几个 Agent 可以快速生成几千行改动。我的工作量没有消失,它从编写转移到了理解、判断和验收。

生成可以并行,理解通常只能串行。

一个 Agent 修改接口,一个 Agent 补充测试,另一个 Agent 调整调用方。它们各自都能完成任务,最后所有结果汇集到我这里。我需要判断接口语义有没有变化,测试是否沿用了错误假设,调用方有没有掩盖异常,几个改动能否同时成立。

机器的带宽增加了,人的带宽没有同步扩展。

当输出超过处理能力,审核质量会自然下降。最初还会逐行看 diff,后来只看摘要;最初会认真检查测试内容,后来看到绿色就继续;最初要求自己理解每个关键决策,后来开始依赖 Agent 提供的变更说明。

疲惫带来的危险,很少表现为明显的错误决定。它更像一种缓慢降低的验收标准。

每一次都只少看一点,每一次都觉得风险可控。几个月以后,代码库里已经出现大量没人完整理解的实现。

不想 review

我现在越来越不想看 AI 写的代码。

人工审核 AI 代码,有时比自己重写还累。自己写代码时,设计过程和实现过程是连续的。我知道哪些地方经过权衡,哪些地方只是临时处理,哪些假设需要后续验证。

面对 AI 生成的代码,这些上下文都要重新推导。

最让人疲惫的代码,往往还写得挺像样。命名规范,结构完整,注释齐全,测试也有。逐段看都有合理性,放回整个系统却经常显得多余。

一个边界条件被扩展成通用框架,一次局部修复引入新的中间层,三个表面相似的流程被强行抽象到一起。代码能运行,测试也能通过,但维护成本被悄悄推高了。

审核者需要花很大力气,才能解释为什么一份「正确」的代码不适合进入当前系统。

重复几次以后,人会开始逃避。既然测试过了,先合进去。出了问题,再让 Agent 修。下一次 Agent 又基于上一次生成的结构继续扩展,代码越来越多,理解越来越少。

最后会出现一种荒诞状态:人不愿意维护 AI 写的代码,于是继续让 AI 维护。

理解变浅

亲手写代码的过程,本身也是建立系统认知的过程。

为了实现一个功能,我需要找到入口,理解依赖,处理编译错误,观察测试失败,再确认数据如何穿过整个链路。实现完成以后,我对这部分系统已经形成了自己的判断。

Vibe Coding 跳过了其中大量过程。

Agent 告诉我改了哪些文件、采用了什么方案、测试结果如何。我可以很快获得一份完整说明,却没有经历那些失败、试探和修正。知道结果,与掌握系统之间,仍然隔着很长一段距离。

这种认知缺口在日常迭代中不容易暴露。Agent 还能继续修改,功能也能继续上线。等到线上故障、复杂重构或性能退化时,团队需要在压力下定位根因,欠下的理解成本才会集中出现。

每个人都参与过系统开发,问到关键链路却只能讲出局部。继续追问异常如何传播、数据如何恢复、容量边界在哪里,回答逐渐变成「让 Agent 分析一下」。

工具还在,工作可以继续。工程师对系统的控制感却在下降。

调度上瘾

多 Agent 会带来很强的生产感。

屏幕上同时跑着几个任务,状态不断变化,代码持续生成。即使我没有处理最困难的问题,也会觉得今天推进了很多工作。

这种感觉很容易上瘾。

我开始热衷于拆任务、写提示词、查看进度、追加要求。一天都在操作,一天都没有停下来。到了晚上,任务列表关闭了不少,却很难指出自己完成了哪段连续思考。

技术管理者更容易陷进去。我们的时间本来就被会议、消息和协作切碎,Agent 又提供了一种产出感很强的碎片化工作。它比回复消息更像研发,比真正做架构设计轻松,还能持续制造「事情正在推进」的反馈。

久而久之,启动任务替代了处理问题,完成数量替代了工程质量。

代码还在,人却远了

Vibe Coding 让我写得更快,也让我离代码更远。

这种距离很难通过提交数量看出来。功能持续上线,测试数量持续增加,仓库每天都很活跃。只有在关掉 Agent、独自面对系统时,才能感受到变化。

我还能不能连续读一小时代码?

能不能在没有摘要的情况下说清楚一次变更?

能不能独立判断某个抽象该不该存在?

线上出问题时,我脑子里有没有完整的执行链路?

这些问题比 token 使用量更让我焦虑。

我仍然每天使用 Vibe Coding,也很难再回到完全手写的状态。它确实提高了生产速度,只是这份速度附带了一组后遗症:心流消失、注意力碎片化、token 焦虑、审核疲劳、理解变浅,以及对调度和即时反馈的依赖。

以前写代码会累,累在实现。

现在也累,累在持续接收、持续判断、持续验收。机器一直在输出,我的大脑一直没有真正下班。

以上。