<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>DeepSeek Harness on 巴别之塔 - Tower of Babel</title>
    <link>https://lqhl.me/tags/deepseek-harness/</link>
    <description>Recent content in DeepSeek Harness on 巴别之塔 - Tower of Babel</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <copyright>Copyright © 2023 - 2024, Qin Liu.</copyright>
    <lastBuildDate>Tue, 18 Aug 2026 14:57:23 +0800</lastBuildDate><atom:link href="https://lqhl.me/tags/deepseek-harness/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Pi 与 DeepSeek Harness：Agent-Friendly 的两种组合方式</title>
      <link>https://lqhl.me/blog/two-paths-to-agent-friendly-systems/</link>
      <pubDate>Tue, 18 Aug 2026 14:57:23 +0800</pubDate>
      
      <guid>https://lqhl.me/blog/two-paths-to-agent-friendly-systems/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pi.dev/&#34;&gt;Pi Coding Agent&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/deepseek-ai/deepseek-harness&#34;&gt;DeepSeek Harness&lt;/a&gt;（下文简称 DSH）都在回答同一个问题：怎样的软件更适合 Agent 使用和修改？&lt;/p&gt;
&lt;p&gt;它们给出了近乎相反的答案。&lt;/p&gt;
&lt;p&gt;Pi 保持一个很小的核心，把组合交给文件、Shell、CLI、进程和可选扩展。DSH 则建立在 &lt;a href=&#34;https://github.com/cordiverse/cordis&#34;&gt;Cordis&lt;/a&gt; 之上，把模型、工具、会话、沙箱乃至 Agent Loop 都组织成 Plugin，再由统一的 Service、Event 和生命周期机制连接起来。&lt;/p&gt;
&lt;p&gt;两者都是 composable 的。真正的区别不在于是否组合，而在于：&lt;strong&gt;组合由谁负责，复杂性放在哪里。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DSH 是一个有趣而有野心的尝试，但我更看好 Pi。它对 Agent 和人类的心智负担都更低，更容易使用、理解和修改。长期记忆与任务状态可以放到进程之外，运行时本身则可以被停止、替换和重建。更重要的是，简单并不意味着不可组合。&lt;/p&gt;
&lt;h2 id=&#34;一场延续至今的设计分歧&#34;&gt;一场延续至今的设计分歧&lt;/h2&gt;
&lt;p&gt;Richard Gabriel 在 &lt;a href=&#34;https://www.dreamsongs.com/RiseOfWorseIsBetter.html&#34;&gt;The Rise of Worse is Better&lt;/a&gt; 中比较了两种软件设计取向。&lt;/p&gt;
&lt;p&gt;第一种是 New Jersey Approach，也就是 Worse is Better。它把实现简单放在最高位置，接受一部分少见场景由用户和外围工具处理。第二种是 MIT Approach，也被称为 the right thing。它更重视接口的正确性、一致性和完整性，愿意用更复杂的实现换取统一的系统语义。&lt;/p&gt;
&lt;p&gt;两者关注的设计指标相同，只是优先级不同：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Worse is Better&lt;/th&gt;
          &lt;th&gt;MIT Approach&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;简单性&lt;/td&gt;
          &lt;td&gt;实现简单优先&lt;/td&gt;
          &lt;td&gt;接口简单优先&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;正确性&lt;/td&gt;
          &lt;td&gt;核心必须基本正确，少见边界可以为简单让步&lt;/td&gt;
          &lt;td&gt;所有可观察行为都应正确&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;一致性&lt;/td&gt;
          &lt;td&gt;必要时可以牺牲&lt;/td&gt;
          &lt;td&gt;与正确性同样重要&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;完整性&lt;/td&gt;
          &lt;td&gt;最容易被牺牲&lt;/td&gt;
          &lt;td&gt;应覆盖所有合理场景&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Gabriel 把早期 Unix 和 C 视为 New Jersey Approach 的代表。它们没有一次提供完整世界，而是先提供容易实现、移植和组合的基本机制，缺少的能力由用户空间程序逐渐补足。这种不完整反而形成了 Unix 的组合传统。&lt;/p&gt;
&lt;p&gt;Common Lisp、CLOS 和 Scheme 是他列举的 MIT Approach 代表。它们追求更完整和一致的语言语义，不愿把系统边界中的复杂情况推给使用者。代价是实现通常更困难，系统也更难快速传播。&lt;/p&gt;
&lt;p&gt;Pi 和 DSH 不是这些项目的直接后继，但它们重现了相似的取舍。Pi 接近 New Jersey，不是因为它缺少 extension，而是因为它优先保持默认核心简单，把少见能力交给外围。DSH 接近 MIT，也不是因为它使用 Plugin，而是因为 Cordis 愿意增加框架复杂度，为所有组件提供统一的依赖、卸载、失败恢复和生命周期语义。&lt;/p&gt;
&lt;h2 id=&#34;pi把组合交给环境&#34;&gt;Pi：把组合交给环境&lt;/h2&gt;
&lt;p&gt;Pi 默认只给模型四个工具：&lt;code&gt;read&lt;/code&gt;、&lt;code&gt;write&lt;/code&gt;、&lt;code&gt;edit&lt;/code&gt; 和 &lt;code&gt;bash&lt;/code&gt;。它没有试图把每一种 Agent 工作流都建模成 Harness 内部的一等概念，而是尽量复用模型和用户已经熟悉的环境：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;文件和知识    → 普通文件、AGENTS.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;命令和工具    → CLI、bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;后台任务      → tmux 或独立进程
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;工作流        → 脚本
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;额外能力      → TypeScript extension
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;持久化状态    → 文件、数据库、事件日志
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pi 不是不能扩展。恰恰相反，它可以通过 extension 增加工具、命令、UI、权限控制和其他工作流。它只是拒绝把这些能力全部塞进默认核心。&lt;/p&gt;
&lt;p&gt;Pi 延续了 New Jersey Approach 的取舍：先把少数基础机制做好，其余能力留给外围组合。如果普通文件已经能保存计划，就不急着发明 Plan Object；如果 Shell 已经能启动另一个进程，就不急着把所有编排都内建进 Agent Loop。&lt;/p&gt;
&lt;p&gt;这种设计对 Agent 和人都有一个直接好处：真实执行路径很短。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;模型决定调用工具 → 工具执行 → 结果返回模型
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;当行为不符合预期时，我们通常可以直接查看 prompt、工具参数、脚本和输出，而不必先理解一套额外的运行时语义。&lt;/p&gt;
&lt;h2 id=&#34;dsh把组合变成运行时的一等概念&#34;&gt;DSH：把组合变成运行时的一等概念&lt;/h2&gt;
&lt;p&gt;DSH 面对同一个问题，却选择把组合正式纳入 Harness。&lt;/p&gt;
&lt;p&gt;它的核心口号是 Everything is a Plugin。模型适配器、工具、技能、会话、文件系统、沙箱、调度、UI 和 Agent Loop 都通过 Cordis 组合。Cordis 不只负责从一个 Registry 找到实现，还试图统一回答：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Plugin 如何声明和获得依赖；&lt;/li&gt;
&lt;li&gt;Service 如何被提供和替换；&lt;/li&gt;
&lt;li&gt;Event 如何连接组件；&lt;/li&gt;
&lt;li&gt;Plugin 初始化失败时如何清理；&lt;/li&gt;
&lt;li&gt;卸载时如何撤销 listener、timer 和注册项；&lt;/li&gt;
&lt;li&gt;Provider 消失后，依赖它的 Consumer 应该怎么办；&lt;/li&gt;
&lt;li&gt;配置变化和热更新如何避免遗留旧状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DSH 的 MIT 气质来自它对统一生命周期语义的追求，而不是 Plugin 机制本身。&lt;/p&gt;
&lt;p&gt;这套设计不是没有价值。当一个 Harness 需要支持很多 Provider、多种产品形态和独立开发的第三方组件时，直接 &lt;code&gt;import&lt;/code&gt; 和条件分支也会逐渐形成一套隐式框架。DSH 至少把这张组件图正式表达出来，使能力、依赖和替换边界可以被枚举和查询。&lt;/p&gt;
&lt;p&gt;问题在于，统一机制不会消灭复杂性，只会重新安排复杂性。一个工具调用不再只是调用一个函数，它可能涉及 Consumer、Service、Provider、Event 和 Plugin lifecycle。增加一个 Provider 也许更容易了，但理解一次完整执行、修改全局语义和排查框架错误可能更难。&lt;/p&gt;
&lt;h2 id=&#34;两种组合方式&#34;&gt;两种组合方式&lt;/h2&gt;
&lt;p&gt;Pi 与 DSH 都可组合，只是组合单位不同：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pi 组合程序、文件和进程；DSH 组合 Plugin、Service 和 Event。&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Pi&lt;/th&gt;
          &lt;th&gt;DeepSeek Harness&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;默认核心&lt;/td&gt;
          &lt;td&gt;小型 Agent Loop 和少量工具&lt;/td&gt;
          &lt;td&gt;统一 Plugin Runtime&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;组合发生在哪里&lt;/td&gt;
          &lt;td&gt;文件、Shell、CLI、进程和扩展&lt;/td&gt;
          &lt;td&gt;Cordis Context 内部&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;能力扩展&lt;/td&gt;
          &lt;td&gt;外部工具或可选 extension&lt;/td&gt;
          &lt;td&gt;Plugin、Service 和 Event&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;状态持久化&lt;/td&gt;
          &lt;td&gt;倾向放到运行时之外&lt;/td&gt;
          &lt;td&gt;更多状态与生命周期进入统一运行时&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;改变能力&lt;/td&gt;
          &lt;td&gt;修改环境，必要时重启&lt;/td&gt;
          &lt;td&gt;重新组合或替换 Plugin&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;理解系统&lt;/td&gt;
          &lt;td&gt;跟随直接代码和命令&lt;/td&gt;
          &lt;td&gt;理解契约与 Plugin Graph&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;失败恢复&lt;/td&gt;
          &lt;td&gt;重启进程，从外部状态恢复&lt;/td&gt;
          &lt;td&gt;在运行时中卸载、回滚和恢复组件&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;复杂性承担者&lt;/td&gt;
          &lt;td&gt;用户、操作系统和外围工具&lt;/td&gt;
          &lt;td&gt;Framework&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主要风险&lt;/td&gt;
          &lt;td&gt;外围约定逐渐散乱&lt;/td&gt;
          &lt;td&gt;Framework 成为新的心智负担&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这个区别不只影响 Agent，也影响人。人类维护者同样需要知道真实执行路径在哪里、状态由谁拥有、失败后如何恢复。Agent 只是让问题更加突出：它没有团队长期积累的隐性记忆，每次进入代码库都要重新构造系统模型，而每一层动态间接都会消耗上下文和推理。&lt;/p&gt;
&lt;h2 id=&#34;为什么我更看好-pi&#34;&gt;为什么我更看好 Pi&lt;/h2&gt;
&lt;p&gt;我的默认选择是 Pi，不是因为小就一定更美，而是因为大多数 Agent 并不需要一个长期存活、可以原地改变自身组成的运行时。&lt;/p&gt;
&lt;h3 id=&#34;更低的共同心智负担&#34;&gt;更低的共同心智负担&lt;/h3&gt;
&lt;p&gt;Pi 复用的是 Agent 和人类都已经理解的对象：文件、命令、进程和代码。这些机制并不完美，却有成熟的查看、调试和组合方式。一个复杂的 Meta-framework 即使为 Agent 生成了完整目录，人类和 Agent 仍然需要先学习它的概念，才能判断真实行为。&lt;/p&gt;
&lt;p&gt;架构抽象只有在减少的复杂性大于自身引入的复杂性时才值得存在。对于多数个人工作流和 Coding Agent，Pi 更容易达到这个条件。&lt;/p&gt;
&lt;h3 id=&#34;让记忆长寿让进程短命&#34;&gt;让记忆长寿，让进程短命&lt;/h3&gt;
&lt;p&gt;Long-running Agent 不等于 long-running process。对话历史、计划、任务状态和外部操作记录可以持久化到文件、数据库或事件日志；运行时则应当可以在明确边界上停止、升级并从 checkpoint 恢复。&lt;/p&gt;
&lt;p&gt;这样做改变了恢复问题：系统不再需要在一个已经部分变化的运行时中正确卸载和替换组件，只需要从已提交的状态构造一个干净的新运行时。&lt;/p&gt;
&lt;p&gt;后者通常更容易推理、测试和回放。进程退出还会自然清理内存对象、listener、timer 和文件描述符，不必要求应用框架为每种资源重新实现一套完美的撤销语义。&lt;/p&gt;
&lt;p&gt;当然，外部副作用仍然需要幂等、日志和补偿机制。但 Cordis 式进程内生命周期同样不能自动撤销已经发出的消息、删除的文件或调用过的外部 API。无论选择哪条路线，真正长期的状态都必须在运行时之外得到管理。&lt;/p&gt;
&lt;h3 id=&#34;agent-让外围-glue-更便宜&#34;&gt;Agent 让外围 Glue 更便宜&lt;/h3&gt;
&lt;p&gt;过去引入通用框架，部分原因是人不愿意反复编写脚本、Adapter 和 Wiring。Agent 很擅长生成和维护这些机械代码，也可以在修改后重建、测试并重新启动系统。&lt;/p&gt;
&lt;p&gt;这降低了显式代码和局部专用化的成本，却没有消除动态框架的理解成本。既然两边的经济性发生了变化，为了减少少量重复而提前引入复杂的运行时，未必仍然划算。&lt;/p&gt;
&lt;h3 id=&#34;简单仍然可以-composable&#34;&gt;简单仍然可以 Composable&lt;/h3&gt;
&lt;p&gt;Pi 没有放弃组合，而是使用更低层、更通用的协议组合：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;标准输入输出
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;文件
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;命令行参数
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;退出码
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;环境变量
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;独立进程
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unix 早已证明，Worse is Better 和 composability 并不矛盾。DSH 通过统一框架获得组合性；Pi 通过操作系统和公开协议获得组合性。后者不够完整，却通常更透明，也更容易替换其中任何一部分。&lt;/p&gt;
&lt;h2 id=&#34;dsh-的价值与举证责任&#34;&gt;DSH 的价值与举证责任&lt;/h2&gt;
&lt;p&gt;我并不认为 DSH 选错了方向。它要构建的是一个开放的 Harness 平台，而不只是固定功能的 Coding Agent。多种模型、工具、沙箱、会话实现和产品形态，确实需要比 Pi 更强的装配能力。对于必须不停机、组件需要独立发布、运行中经常替换能力的系统，完整生命周期也可能值得支付成本。&lt;/p&gt;
&lt;p&gt;但动态性不应该因为未来可能需要就成为默认。DSH 需要用真实使用证明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;动态替换是常见需求，而不只是演示；&lt;/li&gt;
&lt;li&gt;Agent 增加和修改能力的总成本确实下降；&lt;/li&gt;
&lt;li&gt;Plugin Graph 比直接代码更容易发现和理解；&lt;/li&gt;
&lt;li&gt;多次加载、卸载和失败恢复后没有残留状态；&lt;/li&gt;
&lt;li&gt;Framework 引入的调试成本小于它消除的组合成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在这些问题得到回答之前，我会把 DSH 看作一个值得关注的实验，而不是 Agent Harness 必然的终局。&lt;/p&gt;
&lt;h2 id=&#34;默认简单按需求增加结构&#34;&gt;默认简单，按需求增加结构&lt;/h2&gt;
&lt;p&gt;Pi 用外部组合保护核心的简单；DSH 用统一运行时保护组合世界的完整。两种设计都成立，但不应该拥有相同的默认优先级。&lt;/p&gt;
&lt;p&gt;我更看好 Pi：保持核心小，把长期记忆放到运行时之外，依靠文件、CLI、Shell、独立进程和可选扩展完成组合。这让 Agent 和人类面对同一套更直接的系统，也让运行时更容易停止、理解、修改和重建。&lt;/p&gt;
&lt;p&gt;DSH 最值得肯定的地方，是它认真处理了动态组合、依赖和生命周期这些困难问题。但复杂性应该由已经发生的需求买单，而不是由一个完整世界的想象提前买单。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在动态运行时被证明不可缺少之前，简单应该是默认选择。&lt;/strong&gt;&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
