DeepSeek Harness 本身是一个比较完整的开源项目,仓库里除了 Agent Runtime,还包含文档站、Benchmark、CI、测试、开发工具、发布相关配置等内容。这些代码对于官方项目的开发和维护都有作用,但如果当前主要目的是阅读 Agent 的实现,全部保留下来会增加不少干扰。因此这一轮精简主要针对外围工程设施,Agent、LLM、Session、Tool、Shell、Filesystem、Storage、Sandbox 等运行时模块基本保留。
1. 第一轮删除的内容
目前主要去掉了 .agents/、.claude/、.github/、benchmarks/、docs/、python/、snapshots/、website/ 等目录。其中 docs/ 和 website/ 主要用于项目文档和网站;benchmarks/ 是 Benchmark 相关内容;.github/ 包含 GitHub Workflow 等配置;snapshots/ 主要服务于测试和结果校验。另外还清理了一些贡献指南、Benchmark 说明、文档配置以及部分测试、验证和发布相关脚本。
这里的精简标准并不是判断某部分代码有没有价值,而是看它是否直接参与 Agent Runtime 的主要运行过程。像 CI、Benchmark、文档和测试,对于一个长期维护的项目当然很重要,只是它们并不会直接参与一次用户消息从输入到 Agent 执行再到最终响应的过程,因此在源码阅读阶段可以暂时拿掉。
经过第一轮处理以后,顶层主要剩下 apps/、native/、packages/、patches/、scripts/ 和 vendor/。真正需要重点看的主要是 apps、packages 和 vendor。其中 apps 是应用入口,packages 是绝大多数功能实现所在的位置,vendor 则包含 Cordis 等 Harness 底层依赖。
2. apps:CLI 和 Web 两个入口
apps 目前保留 cli/ 和 web/ 两个应用。cli 提供命令行入口,web 提供 Web 端入口。它们本身并不是 Agent 的核心实现,更接近于 Harness Runtime 的不同交互界面。用户可以从 CLI 输入消息,也可以从 Web UI 输入消息,但最终都会进入下面的 Agent 运行流程。
可以简单理解为 CLI / Web -> Harness Runtime。这种结构把交互层和 Agent Runtime 分开,后面的 Agent、Session、Tool 和 LLM 并不需要关心用户究竟是从 CLI 还是 Web 发起任务。对于源码阅读来说,也没有必要一开始就钻进 Web 前端,可以先顺着 CLI 或 Runtime 的启动流程找到 Agent 的初始化位置,再继续向下追。
3. packages:主要功能基本都在这里
精简之后,代码量最大的部分仍然是 packages。这里并不是一个巨大的 Agent 实现,而是拆成了很多独立 package,包括 core、llm、session、storage、shell、fs、subprocess、terminal、sandbox、ssh、mcp、skill、workflow、browser-use、computer-use 等。
这些 package 分别负责不同能力。模型调用、Session、工具系统、文件操作、Shell、终端、存储、Sandbox 等功能并没有全部堆在一个模块里,而是通过插件和服务组合起来。这也是 DeepSeek Harness 比较明显的一个架构特点。
所以第一轮精简没有继续大规模删除 packages。一些看起来暂时用不到的模块,实际上可能被其他 package 依赖;还有一些模块虽然不属于 Agent Loop 本身,但提供了 Tool、Storage 或执行环境等基础能力。在没有把依赖关系和初始化流程看清楚之前,继续按照目录名称删除意义不大。
4. core:Agent 的主要骨架
首先需要关注的是 packages/core/。当前保留下来的主要模块包括 agent/、agent-default-model/、agent-loop/、agent-tool-presentation/、scope/、session/、system-prompt/ 和 tools/。
从目录名称基本可以看出这一层的作用。agent 负责 Agent 本身的定义和管理;agent-loop 负责驱动任务执行;session 负责运行过程中产生的数据和事件;system-prompt 负责 System Prompt;tools 负责工具的注册、描述和执行;scope 则与运行上下文和作用域有关。
暂时忽略内部实现,可以先把主要关系理解成 Agent -> Agent Loop -> Session / System Prompt / Tools / LLM。这并不代表实际源码中的完整依赖关系,只是方便建立第一层认识。后面继续读源码时,再把这些关系替换成真实的 Service、Context、事件和函数调用。
5. Agent Loop:控制一次任务如何向前执行
packages/core/agent-loop/ 是核心部分之一。普通的 LLM 调用通常只有 User -> LLM -> Response,而 Agent 的执行过程不是一次模型请求就结束。模型可能返回 Tool Call,Harness 执行工具后把结果重新放回上下文,再次请求模型。一次任务可能经历多轮这样的过程,直到模型不再调用工具并产生最终响应。
整个过程可以简化为 User -> LLM -> Tool Call -> Tool Result -> LLM -> … -> Final Response。Agent Loop 就是负责推动这条链路持续运行的部分。除了调用模型和执行 Tool,它还需要处理 Step、Turn、上下文更新、结束条件以及执行过程中产生的各种事件。
因此后面分析 Harness 的完整调用链时,agent-loop 会是一个重点。现阶段先保持原实现不动,通过实际运行流程把模型调用、Tool 执行和 Session 更新之间的关系看清楚,再考虑是否需要调整这一层。
6. Session:保存的不只是聊天消息
Session 相关代码主要分布在 packages/core/session/ 和 packages/session/。Harness 的 Session 并不只是维护一个不断追加的 messages[],运行过程中发生的事情会以事件形式进入 Session,例如用户消息、模型输出、Tool Call 和 Tool Result 等。
一次简单执行可能包含 turn/start、user/message、step/start、assistant/message、tool/call、tool/result、step/end、turn/end 等事件。模型后续需要的上下文,再根据 Session 中保存的数据构造出来。因此 Session 保存的是 Agent 的执行历史,而不只是最终展示给用户看的聊天文本。
这种设计对于 Agent Runtime 很重要,因为一次任务通常包含大量中间状态。如果只保存用户消息和最终回答,Tool 到底执行了什么、返回了什么、模型拿到结果以后又做了什么都会丢失。以事件形式保存以后,后续的恢复、回放、分支、调试以及执行记录分析都会更容易实现,因此 Session 属于目前需要完整保留的核心代码。
7. Tools:连接模型和实际能力
Tool 相关的核心代码主要位于 packages/core/tools/。LLM 本身不会直接执行 Shell,也不会自己读取文件。模型能做的是根据提供给它的 Tool Schema 产生一次工具调用,然后由 Harness 找到对应 Tool 并执行,最后再把执行结果返回给模型。
这条链路可以简单理解成 LLM -> Tool Registry -> Tool Implementation -> Filesystem / Shell / Browser / … -> Tool Result -> LLM。Tool 系统实际上就是模型和真实执行环境之间的连接层。
后面无论增加进程管理、systemd、Docker、网络管理还是其他系统能力,本质上都可以继续沿着这一层扩展。新的能力按照 Harness 的 Tool 机制注册进去以后,Agent Loop 不需要知道某个具体工具内部是怎样实现的。后续专门分析 Tool 时,还需要继续看 Tool Schema 如何生成、工具如何注册、模型怎样获得工具列表、调用参数如何校验,以及 Tool Result 最终怎样重新进入 Session 和模型上下文。
8. LLM:把 Agent Runtime 和模型分开
模型相关实现主要位于 packages/llm/,其中包含 LLM 基础接口、DeepSeek Provider、API 扩展、Retry 和 Token Meter 等内容。Agent Loop 并不是直接把 DeepSeek API 请求写死在自己的实现中,而是通过 LLM 层与具体模型进行交互。
可以先理解成 Agent Loop -> LLM Interface -> Model Provider -> DeepSeek API。这样 Agent 的执行逻辑和具体模型 Provider 被分开,模型请求格式、API 差异、重试策略等可以留在 LLM 层处理,而 Agent Loop 主要关注一次任务应该怎样继续运行。
这一部分目前没有太多精简的必要。后续主要需要搞清楚 Agent Loop 调用 LLM 的入口,以及模型返回的 Tool Call 怎样进入下一阶段。
9. Shell、Filesystem、Subprocess 和 Terminal
如果关注 Agent 操作系统的能力,那么 packages/shell/、packages/fs/、packages/subprocess/ 和 packages/terminal/ 会比较重要。
shell 下面已经包含 bash-local、bash-sandbox、shell、shell-env、tool-bash、tool-bash-persistent 等模块;fs 中则可以看到 fs、fs-local、fs-sandbox、tool-fs、tool-fs-search、tool-str-replace-editor 等实现。除此之外,还有本地 Subprocess、Terminal 和 Bash Terminal 等相关代码。
这些模块已经覆盖了命令执行、文件读写、子进程和终端等比较基础的系统能力,因此在精简过程中全部保留。这几个模块后面值得放在一起看,重点不只是某个 Bash Tool 怎样调用命令,而是 Harness 如何抽象执行环境。
local 和 sandbox 的存在说明上层 Tool 与底层实际运行位置之间已经存在一定程度的分离。上层 Tool 尽量不直接依赖具体环境,而是通过相应能力层访问 Local 或 Sandbox。这样的结构也为以后扩展其他执行环境留下了空间。
10. Storage 和 Sandbox
Storage 目前保留的内容主要包括 storage/、storage-domain/、storage-json/ 和 storage-sqlite/。这一层负责持久化相关能力,Session、配置以及其他运行数据最终都需要落到某种存储实现中,而 JSON 和 SQLite 提供了不同的实现方式。
Storage 和 Agent Loop 的关系没有 Session、Tool 那么直观,但它属于 Runtime 的基础设施,因此目前没有继续精简。
Sandbox 相关部分主要包括 sandbox/、sandbox-local/ 和 sandbox-policy/。对于能够执行 Shell、访问文件系统的 Agent 来说,Sandbox 并不是单纯的外围功能。Tool 决定 Agent 可以调用哪些能力,Sandbox 和 Policy 则进一步涉及这些能力在哪里执行、允许执行到什么程度。
后面分析 Bash、Filesystem 等工具时,也需要把 Sandbox 一起带上,否则只看 Tool 本身很难得到完整的执行链。
11. vendor 和 Cordis
vendor/ 目前也保留,其中可以看到 Cordis、Cosmokit、Loader、Schemastery 等代码。这里最重要的是 Cordis,因为 DeepSeek Harness 的插件系统建立在它上面,前面提到的 Agent、Session、Tool、LLM 等模块最终都需要通过插件和 Context 组合到一起。
现阶段没有必要直接从 Cordis 的底层实现开始阅读。更合适的方式是先顺着 Harness 的启动代码,看一个 Plugin 是怎样注册的、Service 是怎样挂到 Context 上的、不同模块之间又是怎样取得彼此提供的能力。等实际遇到 Cordis 的 Context、Service、Event 等机制时,再进入 vendor/cordis 对照实现。
这样阅读会更容易区分哪些设计属于 Harness,哪些设计实际上来自 Cordis。
12. 精简后的整体结构
经过第一轮裁剪,可以先把主要代码理解成几个层次:最上面是 CLI 和 Web 等应用入口;下面是 Agent 和 Agent Loop;Agent Loop 在执行过程中与 Session、Tools 和 LLM 交互;Tools 再连接到 Filesystem、Shell、Terminal 等系统能力;这些能力最终通过 Local、Sandbox 等执行环境与操作系统交互。
这个结构只是源码阅读阶段的简化模型,并不是 Harness 的完整架构。Storage、System Prompt、Scope、Credentials、MCP、Skill、Workflow 等模块暂时都没有展开,后面分析到对应代码时再逐步补充。
第一轮精简到这里基本就够了。继续删除之前,需要先把现有模块之间的依赖关系和实际启动流程看清楚,否则很容易把表面上独立、实际上参与初始化或运行时依赖的 package 一起删掉。
下一篇可以从项目启动开始,顺着真实源码看 Cordis Context 是怎么创建的、插件是怎么加载的,以及 Agent、Session、Tool、LLM 最后是怎么被组装到同一个 Runtime 里的。再往后继续拆 Agent Loop、Session、Tool 和 Shell 等模块,把整个 Harness 的调用链逐步串起来。


