Skip to content
签到签到

第 5 章:DeepSeek Harness 架构

本章解决的问题

前端面试如果聊到 Agent 平台,你需要能说清一个可扩展 Agent 运行时为什么需要插件化,而不是把所有工具写进一个主循环。

交互图解:Agent、Harness 与插件服务全景 · 查看图解导读

大白话理解

DeepSeek Harness 像一块插线板:

  • 每个能力是一个插件。
  • 插件占用一个稳定的服务名,例如 ctx.toolsctx.llm
  • 插件通过声明依赖来决定加载时机。
  • 插件注册的东西可以撤销。

这样,换模型、换沙箱、换 UI 都只是替换插件,不需要重写主循环。

必须掌握的概念

1. Context

Context 是运行时服务仓库。插件通过 ctx.<key> 找到其他服务。

2. Service

Service 是声明了稳定键的能力,例如:

  • ctx.sessions
  • ctx.systemPrompt
  • ctx.tools
  • ctx.agents
  • ctx.agentLoop
  • ctx.llm

3. Profile 与 Bundle

一个运行中的 dsh 是一棵插件树,由多个配置层组成:

text
bundle patch
-> profile patch
-> home patch
-> --patch overlay

后写的层优先。webheadless 是两种官方 profile。

4. Patch 不是深度合并

Patch 通过 id 覆盖目标行的完整 config。覆盖时必须重述要保留的字段。

DeepSeek Harness 对应实现

核心服务表

服务职责
ctx.sessions会话日志和内存 store
ctx.systemPrompt组装 prompt 和 tool schema
ctx.tools工具注册和执行管线
ctx.agentsAgent 公共接口和 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 通信。
  • 前端展示来自统一事件流的数据。

自测题

  1. ctx.toolsctx.llmctx.sessions 分别负责什么?
  2. 为什么 patch 覆盖时需要重述整行 config?
  3. dsh-basedsh-web-app 的关系是什么?
  4. 新工具插件为什么不需要改 Agent Loop?

本章小结

DeepSeek Harness 的架构可以用一句话概括:用可组合、可撤销的插件服务代替硬编码主循环。前端理解这一点,就能回答“AI 平台为什么需要插件化”这类架构题。

进一步阅读:

  • docs/architecture.md
  • packages/bundle/base/cordis.patch.yml