DeepSeek Harness(架构篇):为什么连 Agent Loop 都能替换?
常见插件机制通常先有固定核心流程,插件再增加主题、命令或工具。
DeepSeek Harness 的设计不同。
Agent Loop 是 Agent 的核心流程:它组织模型判断、工具执行和结果反馈,并决定继续还是结束。按照常见的插件思路,这部分会写在软件核心里,插件只能围绕它扩展。
但官方架构文档明确把 Agent Loop 与模型适配器、工具注册表、会话日志一样做成了插件。
连 Agent 的核心流程都能替换,正是 DeepSeek Harness 与常见插件机制最大的区别。
这里的"能力边界",可以理解为部件之间约定好的插座:它规定请求怎样传入、结果和错误怎样返回,却不限定背后必须接哪一个具体实现。插座不变,模型适配器、文件系统或 Agent Loop 就能更换。
一、这里的插件不是外挂,而是产品本身
常见的插件系统通常可以画成这样:
固定 Agent Loop + 外围插件
主程序决定工作流程,插件只能在预留位置增加功能,很难换掉内部的模型适配器或执行循环。DeepSeek Harness 更接近另一种结构:
稳定接口 + 包含 Agent Loop 的可组合插件
模型调用、工具执行、会话记录、文件系统、沙箱和 Agent Loop,本身就是组成默认产品的插件。这里不再保留一条只有官方才能修改的 Agent 核心流程。不过,"Everything is a Plugin"不等于系统没有公共规则。插件仍要遵守接口、依赖和运行约定。
真正被取消的,是某个默认实现天然不可替换的特权。

二、插件树不是功能清单,而是一份 Agent 组装图
官方把运行中的 dsh 描述为一棵插件树。
它记录本次启动装入了哪些部件、由谁提供。
在 .dsh/profiles/ 目录中,可以看到 Web 与 Headless 两套 Profile:

Web 配置里可以看到这些独立条目:
- id: llm
name: '@deepseek-ai/dsh-llm'
- id: session
name: '@deepseek-ai/dsh-session'
- id: tools
name: '@deepseek-ai/dsh-tools'
- id: agent-loop
name: '@deepseek-ai/dsh-agent-loop'
- id: web-runtime
name: '@deepseek-ai/dsh-web-app'Headless 配置仍然保留 llm、session、tools 和 agent-loop,但不再装入 Web 界面,结尾换成自己的启动器与运行器:
- id: headless-startup
name: '@deepseek-ai/dsh-headless/startup'
- id: headless-runner
name: '@deepseek-ai/dsh-headless'这里的 Headless,指不启动网页和服务器的命令行入口。它接收一个任务,等待 Agent 完成,打印最终回复后退出。
它适合一次性脚本,但不等于官方所说的 SDK 方式。
Python SDK 是另一条程序化入口。调用方可以启动完整的 Harness 运行时,复用进程、管理会话、连续提交任务并订阅事件。
SDK 与运行时通过标准输入输出上的 JSON-RPC 通信,不使用 Headless 的一次性任务运行器。
三种入口可以这样区分:
| 入口 | 场景 |
|---|---|
| Web | 浏览器交互 |
| Headless | 命令行提交一次任务,输出结果后退出 |
| SDK | 由另一个程序持续控制 Harness 运行时 |
它们的共同点,是入口没有与模型、工具、会话和 Agent Loop 焊死。 Web 与 Headless 的配置对照已经显示,同一批底层插件可以接到不同入口;SDK 则进一步允许外部程序驱动另一套完整的插件组合。
三、能替换的前提,是把能力、实现和使用者分开
把代码拆成很多包,不等于实现可以替换。 上层模块直接绑定具体实现,换实现时仍要跟着改。
DeepSeek Harness 对一项可替换能力区分三个角色:
- **能力接口:**像插座一样,规定输入、输出和错误应该是什么样;
- **提供者:**负责真正实现这项能力;
- **使用者:**通过接口调用能力,完成更高层任务。
可以把关系压缩成一行:
使用者 → 稳定能力接口 ← 当前提供者
以文件操作为例。
上层工具只关心读取、写入和搜索文件。本地文件系统和远程沙箱都可以成为提供者;只要履行相同约定,上层工具就不需要为每种环境复制一套实现。
命令执行也是如此,真正运行命令的可以是本机 PowerShell、受限沙箱或远程环境。
可替换也不是随便互换。新的提供者仍要正确处理权限、路径、错误反馈和生命周期。
四、模型、工具和会话,是三条独立边界
理解了能力接口,再看模型、工具和会话,插件架构就不再抽象。
**模型边界:**负责接入不同模型提供方。Agent Loop 发出统一的模型请求,适配器负责把请求转换成具体提供方能够理解的协议。更换模型实现,不要求 Loop 理解每个厂商的接口细节。
**工具边界:**负责注册当前 Agent 能看到的工具,并管理调用真正执行前后的处理流程。文件、命令和其他能力可以分别加入,而不是把所有工具代码塞进 Agent Loop。
**会话边界:**负责记录用户消息、模型回复、工具调用和工具结果。恢复、分叉、回放等能力都可以从这份记录派生,而不是依赖 Web 页面里暂时显示的对话内容。
一次任务大致这样经过三条边界:
Agent Loop 请求模型
→ 模型选择工具
→ 工具执行并返回结果
→ 结果写入会话
→ Agent Loop 判断是否继续三条边界协作但互不绑定,更换其中一个,不必重写其余能力。
五、为什么连 Agent Loop 都能替换
按照常见的插件机制,Agent Loop 属于软件核心,插件只能在它周围增加能力。
DeepSeek Harness 则把**"外部怎样使用 Agent"与"Agent 内部怎样推进任务"**分开了。
Web、Headless 或 SDK 只需要知道怎样创建 Agent、提交任务和读取状态;收到任务后怎样推进,则由 Agent Loop 插件决定。源码中的 agent 包提供公共约定,@deepseek-ai/dsh-agent-loop 是官方给出的默认调度实现。
更换 Agent Loop 时,不必连界面、SDK、会话和工具系统一起重写。
另一套调度器只要遵守相同约定,就能继续使用这些能力。
"可替换"不是删除 Loop,而是允许换成不同的实现。替换者仍要处理能力依赖、状态一致性、错误和运行顺序;插件化只提供选择,不保证新 Loop 效果更好。
结语
真正开放的是能力边界,不是插件数量。
现在可以回答开头的问题:如果 Agent Loop 都是插件,DeepSeek Harness 还有没有核心?
有。
稳定的是能力接口与协作约定;可变化的是当前装入的具体实现。
以后再看到一个 Agent 框架声称"支持插件",可以先问三个问题:
- 能替换的是外围功能,还是模型、工具、状态和执行循环等关键能力?
- 上层模块依赖稳定接口,还是直接绑定默认实现?
- 替换一个提供者时,其他模块是否需要跟着复制或改写?
常见插件机制扩展 Agent Loop,DeepSeek Harness 连 Agent Loop 本身也能替换。这才是"Everything is a Plugin"最关键的区别。
下一篇,我会沿一条真实请求继续往里走,看看 turn、step、模型调用、工具执行和结果回传怎样串成一次完整任务。