Skip to content
登录

DeepSeek Harness 技术笔记:Cordis 插件内核、事件溯源与 Agent 执行

Updated View as Markdown

官方资料:DeepSeek Harness · 中文架构文档 · Cordis 入门 · 核心包 · Session · 工具

本文按 2026-10-15 官方 master 的架构文档、包说明整理。官方仍标注 Developer Preview,存在破坏性 API 变化风险。English Studio 部分仅是工程取舍分析,非已实现事实。

先建立心智模型

DeepSeek Harness(dsh)是一个基于 Cordis 的可组合 Agent Harness。 它不把模型、工具、会话、Loop、UI 都写成固定类的字段,而是把它们拆成在统一 Context 中注册服务的插件。扩展新功能时,原则上不是“修改大内核”,而是“安装或替换一项插件能力”。

与 yoagent “尽量让执行循环保持小核心”不同,dsh 更强调整个产品的插件化组合边界。

DEEPSEEK / EVERYTHING IS A PLUGINCordis 组合插件,而不是一个不可替换的大内核
01
Profile / Bundles按配置选择基础包、插件与覆盖层
02
Cordis Context服务注入、生命周期、事件与可逆注册
Agent Loop执行驱动
Session Log事件真源
Tools受保护执行
LLM Adapter模型协议适配
这些能力同处 Cordis Context 的插件组合内,可分别替换和挂载;插件依赖、事件与作用域由 Cordis 管理。

Cordis 内核本身负责什么?

Cordis 负责插件的装载/卸载、依赖与上下文、服务注册、带类型的事件以及可逆副作用(effect)。它不直接承担英语学习、模型调用或工具执行业务。

插件向共享 Context 提供服务,按需依赖别的服务。注册项受生命周期管理,插件卸载时相应效果可以被撤销。

术语 直观理解
Context(ctx) 插件连接服务、事件和能力的共同入口
Plugin 向 Context 声明或实现一项能力
Service / Seam 对外公开接口,背后可由不同 Provider 实现
Typed Events 插件之间的事件型扩展点
Scope / Realm 限制能力和注册项作用范围
Profile / Bundle 按场景装配的插件配置集合

比如“将文件执行迁移到隔离沙箱”,可以通过更换相关文件系统和进程执行 Provider 来实现,而不应在每一种工具中分别硬编码远程执行逻辑。

一、核心包如何协作?

官方 核心子系统文档 将一次执行拆成多个相互配合的包:

组件 Context 接口 负责什么
core/session ctx.sessions 追加式会话事件日志
core/system-prompt ctx.systemPrompt 组装 Prompt 片段与工具 Schema
core/tools ctx.tools 工具注册、作用域及守卫执行
core/agent ctx.agents 公共 Agent 接口和注册表
core/agent-loop ctx.agentLoop 默认 Agent 驱动器
core/scope 非服务库 为能力按 Agent 限定作用域
llm/llm ctx.llm 消息/流协议和模型适配器

其中一个细节尤其重要:外部消费者依赖 ctx.agents,而不是直接依赖具体 agent-loop 的实现。 默认 Loop 向注册表提供 AgentFactory。这使未来替换循环实现时,UI、工具与其它插件不需要全部跟着改。

dsh 的 Profile 由多层 Bundle 和用户配置组合而成,例如 Web、SDK 或 Headless 等不同启动方式。并不是每种运行模式都要加载完整 Web 产品。

二、Agent 的 Turn 与 Step 如何运转?

dsh 使用与部分 Agent 框架不同的粒度定义:

概念 dsh 中的含义
Session 一份持久的 Agent 交互事件历史
Turn 从接纳任务到没有剩余工作的一轮执行,可能包含零个或多个 Step
Step 一次模型请求以及该次请求产生的工具执行
Agent 有 send、cancel、whenIdle 等能力的运行句柄

因此不能把其它框架的 “Turn = 一次模型调用” 不加说明地移植过来。dsh 的 Step 更接近这个单次模型和工具的单位。

DEEPSEEK / TURN & STEP一次 Turn 可以包含多个 Step
01
Turn Start → Inbox认领待处理输入和后续消息
02
agent/pre-step插件可决定接受、修改或拒绝当前输入
03
Request / LLM Stream准备路由、冻结历史、流式输出
04
Tool Pipelinetools/pre-execute → execute → post-execute
05
事件入 Session Log记录 model-visible 事实,然后检查是否需要下一 Step
06
agent/turn-stopping → Turn End本轮不再欠下工作时结束
仍欠工具回传或有下一步输入 → 新 Step(同一 Turn)
Step 是一次模型请求及其工具;事件分别进入持久 Session Log 和 live agent/capability 事件通道。

一次 Step 的简化执行路径:

  1. agent-loop 从 Inbox 中认领输入,开启 turn/start。
  2. ctx.systemPrompt 根据片段、变量和工具 Schema 构建上下文。
  3. agent/pre-step 插件决定是否接受或修正当前输入。
  4. agent/request 之后通过 ctx.llm.prepareCall() 解析实际模型路由,确定本次请求。
  5. Stream 输出助手回复,工具调用经过受守卫的工具管线。
  6. 模型可见的消息、工具结果等追加进 Session 日志;如果还有工作,进入下一 Step,否则触发 agent/turn-stopping 并关闭 Turn。

关键约束:每次模型看到的事实,应该能由持久日志重新构建。 这样才能做可信的回放、恢复和问题排查。真实实现对于取消、重试、失败的记录时机和请求冻结还有更严格约定,不能简单等同于“收到一个 token 就落盘一个 token”。

它如何拦截执行?

dsh 的事件主要分成三个领域:

事件域 职责
session/event 发送已经写入 Session Log 的持久事件
agent/* 观察和干预实时 Agent 行为:请求、步骤、状态、继续
tools/* / fs/* 等 挂接工具、文件系统等具体能力的策略

部分事件采用 Waterfall(瀑布式)处理器:插件调用 next() 才能把执行继续交给后继逻辑。这不同于单纯的“监听通知”事件。比如 tools/pre-execute 参与工具准入,tools/post-execute 可以做结果处理;不要把它们都当成无返回值的观察器。

三、事件溯源:为什么 SessionEvent 是核心设计?

dsh 的 Session 不把一份“最终消息数组”作为唯一持久状态,而将交互写成仅追加的类型化 SessionEvent 日志。模型历史由事件投影而来。

DEEPSEEK / EVENT SOURCING事件为真源,模型历史与 UI 状态均由投影派生
01
Append-only SessionEvent Logturn/start、step/start、user/message、tool/result 等
02
投影(Projections)按规则从相同事件流推导不同视图
deriveMessages()LLM 请求历史
UI / Transcript可重放展示
Resume / Replay恢复会话
持久事实写入 SessionEvent 追加日志;进程内的流式 chunk 不等于完整持久事件记录。

典型持久事件包括:

  • turn/start 与 turn/end
  • step/start 与 step/end
  • user/message、assistant/message、tool/call、tool/result
  • 提示词和请求相关事件,以及其它插件注册的类型化事件

例如一次语法诊断任务:

{
  "kind": "illustrative-learning-result",
  "session_id": "grammar-session-001",
  "weakness": "present_perfect_continuous",
  "outcome": "needs_practice"
}

上面的 JSON 只是 English Studio 可以设计的业务事件示例,不是 dsh 官方 SessionEventMap 已定义的事件格式。真正集成时应通过框架提供的事件扩展契约登记并校验,而不是直接追加任意 JSON。

事件溯源带来什么?

需求 事件日志的优势 仍需注意
重新打开历史 由日志重新投影模型上下文与 UI 回放器须理解事件版本
恢复中断 识别已提交的 Turn/Step/结果 外部工具副作用仍需幂等
定位问题 追踪输入接纳、请求、结果和失败 需谨慎记录敏感数据
扩展业务事件 通过插件扩展 SessionEventMap 不能随意破坏已有投影

实时模型流和已持久化历史也不是同一种东西:agent/assistant-stream 可以给 UI 推送临时 chunk,而稳定记录以最终落入日志的消息或 attempt 为准。若进程在提交前硬中断,不能假定流过的每个 token 都已持久化。

四、工具为何也必须成为可替换的能力?

dsh 的工具不是裸函数数组。ToolDefinition 包含面向模型的 ToolSchema、规范化的输出契约、执行函数和可选运行元数据。

官方 工具子系统 特别强调:

  • 模型只能看到工具名、描述与参数 Schema 等允许字段,不能看到宿主专属的执行策略。
  • 工具成功输出要符合声明的 JSON Schema,并通过投影生成模型可见内容。
  • 工具执行经 tools/pre-execute → tools/execute → tools/post-execute 管线,可附加权限或输出修正。
  • isConcurrencySafe 明确声明允许并发的工具;没有安全声明的操作会按独占约定执行。
  • maxParallelToolCalls 限制并行安全工具的同时在途数量;独占工具仍需要排序屏障。

下面是官方文档中的配置思想(该 YAML 是 dsh 声明式配置示例,不是 Rust 配置):

- name: '@deepseek-ai/dsh-agent-loop'
  config:
    maxParallelToolCalls: 10
    agents:
      - id: 'main'
        provider: deepseek
        model: deepseek-chat
        reasoningEffort: high
        cwd: /workspace

这展示了 Loop 也只是被挂载的一项插件。调用方还可以通过 ctx.agents.create() 和 ctx.agents.resume() 创建与恢复 Agent,拿到有明确 dispose() 责任的 AgentHandle。这比“全局单例里放所有 Agent 状态”更利于隔离与回收。

五、Extension 和插件边界怎么设计?

可以用三个问题判断该写在哪一层:

需求 最接近的扩展点 不推荐
更换模型后端 ctx.llm 的 Adapter 在 Agent Loop 内硬编码不同 API
新增语法查询工具 ctx.tools 注册 ToolDefinition 把业务逻辑混进 agent-loop
会话按不同用户隔离 Agent Scope 和业务身份规则 所有 Agent 复用同一可变全局上下文
新增长期学习记忆 独立 Memory Service 与 Tool/事件适配 强迫 Session Log 承载全部长期业务数据库
添加进度和审计 事件消费者、投影或遥测扩展 每个工具都手写一套日志系统

插件注册还有生命周期:加载后注册服务和事件,在卸载时应撤销效果;Agent 自己的 Scope 负责本地注册项随销毁而清理。

六、对 English Studio 的借鉴与取舍

你已经选择了 Rust Harness 和独立 OpenViking 服务,因此不必为了借鉴 Cordis 就整体迁移到 TypeScript dsh。真正值得复用的是其能力边界:

dsh 的原理 English Studio 的建议
基于接口访问 Agent Rust AgentRuntime 公开统一创建、执行、取消和恢复能力
Provider / Tool / Loop 解耦 模型适配、工具注册、循环由接口或 Trait 隔离
SessionEvent 持久事实 Durable Session 保存会话与工具状态,支持派生与追踪
Agent Scope 听力/语法/词汇三个 Agent 独立消息与工具权限
Tool Schema + Guard 对修改学习数据的工具进行参数校验、授权和幂等
Plugins + Lifecycle OpenViking Gateway 等服务可独立托管及关闭
组合配置 以 AgentDefinition 配置不同专业 Agent,而不是复制三套 Harness

特别注意三个系统不要合并

  • Session Store:当前 Agent 的事件和消息历史。
  • OpenViking:跨会话长期学习记忆及检索。
  • Learning DB:错题、词汇卡、正确率、复习排期等结构化业务事实。

这三者可以关联,但职责不相同。dsh 的 Event Sourcing 不代表需要取消 English Studio 的结构化 Learning DB。

总结:记住三个结论

  1. 组合:“一切皆插件”意味着服务由 Context 发现,由 Profile/Bundle 组合,由生命周期管理。
  2. 执行:Agent Loop 只是实现公共 Agent 接口的一个 Provider;Turn 包含多个 Step,工具经过受保护的管线。
  3. 状态:SessionEvent 是持久事实;模型上下文和 UI 状态由投影派生,真实工具副作用仍需业务级恢复策略。

进一步阅读:官方架构说明 · Cordis 基础 · 核心 Agent 语义 · Pi Harness 技术笔记 · yoagent 技术笔记

Navigation

Type to search…

↑↓ navigate↵ selectEsc close