第 5 章:DeepSeek Harness 架构
本章解决的问题
前端面试如果聊到 Agent 平台,你需要能说清一个可扩展 Agent 运行时为什么需要插件化,而不是把所有工具写进一个主循环。
交互图解:Agent、Harness 与插件服务全景 · 查看图解导读
大白话理解
DeepSeek Harness 像一块插线板:
- 每个能力是一个插件。
- 插件占用一个稳定的服务名,例如
ctx.tools、ctx.llm。 - 插件通过声明依赖来决定加载时机。
- 插件注册的东西可以撤销。
这样,换模型、换沙箱、换 UI 都只是替换插件,不需要重写主循环。
必须掌握的概念
1. Context
Context 是运行时服务仓库。插件通过 ctx.<key> 找到其他服务。
2. Service
Service 是声明了稳定键的能力,例如:
ctx.sessionsctx.systemPromptctx.toolsctx.agentsctx.agentLoopctx.llm
3. Profile 与 Bundle
一个运行中的 dsh 是一棵插件树,由多个配置层组成:
text
bundle patch
-> profile patch
-> home patch
-> --patch overlay后写的层优先。web 和 headless 是两种官方 profile。
4. Patch 不是深度合并
Patch 通过 id 覆盖目标行的完整 config。覆盖时必须重述要保留的字段。
DeepSeek Harness 对应实现
核心服务表
| 服务 | 职责 |
|---|---|
ctx.sessions | 会话日志和内存 store |
ctx.systemPrompt | 组装 prompt 和 tool schema |
ctx.tools | 工具注册和执行管线 |
ctx.agents | Agent 公共接口和 registry |
ctx.agentLoop | 默认 Agent 驱动器 |
ctx.llm | 模型 adapter 和流式调用 |
最小组合
dsh-base 是每个 profile 的第一层。它插入:
- LLM
- Session
- Tools
- Agent Loop
- 权限和沙箱
- 文件系统、Shell 和 Web 等工具
dsh-web-app 再增加 Web Host 和浏览器插件。
dsh-headless 再增加一次性任务 runner。
这些配置位于 packages/bundle/base/cordis.patch.yml 等文件。
为什么插件化重要
如果没有插件化,前端增加一个工具可能要改:
- 主循环
- 工具列表
- 权限判断
- 前端渲染
- 测试 fixture
插件化后,新工具只注册到 ctx.tools,Schema 会自动进入 prompt,UI 通过统一事件或工具视图渲染。
代码示例
下面是一个简化的插件概念示例:
ts
type Effect = () => void
class Context {
private services = new Map<string, unknown>()
provide<T>(key: string, value: T): Effect {
this.services.set(key, value)
return () => {
this.services.delete(key)
}
}
get<T>(key: string): T {
const value = this.services.get(key)
if (!value) throw new Error(`missing service "${key}"`)
return value as T
}
}
const ctx = new Context()
const disposeSessions = ctx.provide('sessions', { log: [] })
// 卸载时撤销
disposeSessions()真实 Cordis 支持依赖等待、事件、fiber 和更复杂的 teardown,但这个例子表达了“服务可注册、可撤销”的核心。
面试怎么问
问:为什么 Agent 平台需要插件化?
回答要点:
- Agent 能力很多:模型、工具、记忆、权限、UI、协议。
- 不同部署需要不同组合。
- 插件化让能力可替换,避免主循环膨胀。
- 注册可撤销,支持热更新和干净卸载。
问:profile、bundle、patch 是什么关系?
回答要点:
- profile 是最终组合。
- bundle 是一组可发布配置。
- patch 是用户覆盖层。
- 后应用层覆盖前一层。
问:前端如何参与这种插件化架构?
回答要点:
- 浏览器端也可以运行自己的插件树。
- UI 插件通过 slot 注册组件。
- 前后端通过类型安全 RPC 通信。
- 前端展示来自统一事件流的数据。
自测题
ctx.tools、ctx.llm、ctx.sessions分别负责什么?- 为什么 patch 覆盖时需要重述整行 config?
dsh-base和dsh-web-app的关系是什么?- 新工具插件为什么不需要改 Agent Loop?
本章小结
DeepSeek Harness 的架构可以用一句话概括:用可组合、可撤销的插件服务代替硬编码主循环。前端理解这一点,就能回答“AI 平台为什么需要插件化”这类架构题。
进一步阅读:
docs/architecture.mdpackages/bundle/base/cordis.patch.yml