DeepSeek Harness 插件化机制、缓存与推理回传解析

本文整理自一次关于 DeepSeek Harness(DSH)框架的深入问答,内容均基于框架源码(node_modules/@deepseek-ai/*)核实的事实,重点覆盖三大主题: ① Agent 插件化架构 ② KV 缓存命中机制 ③ 思考模式下的推理回传(reasoning passback)


目录

  1. 会话环境与背景

  2. Agent 预设:PTC 模式与其他内置模式

  3. 插件化架构:最小核心 + 事件驱动插件

  4. 上下文压缩:一个典型的插件体系

  5. 轨迹(Trajectory):会话过程的完整档案

  6. KV 缓存命中机制

  7. 推理回传(Reasoning Passback)

  8. 总结


一、会话环境与背景

本次对话从环境认知开始,经历了 LightRAG 与知识图谱文档对比、PTC 模式探源、轨迹(trajectory)解析、插件架构(loop、compaction)、缓存命中机制,最后深入推理回传机制。本文聚焦后四个技术主题。


二、Agent 预设:PTC 模式与其他内置模式

2.1 预设即"插件组装"

DSH 官方定义:

预设(Agent preset)即一个会话的 Agent 所运行的插件组装——它的工具、提示词与能力。 复制一份既有预设改成自己的,或用「创造模式」让 Agent 帮你创建。

预设对"此后新建的会话生效,运行中的会话保持它开始时的预设"。

2.2 四种内置预设

预设 | 说明 -- | -- 标准模式 | 功能完整的编码 Agent:文件编辑、Shell、文件/网页检索、Skills、计划、目标、子代理、工作流 PTC 模式(Code mode) | 标准模式全部能力 + Code Mode SDK:工具以异步绑定形式暴露,模型可写一段 TypeScript 程序(支持顶层 await/return)在一次运行中组合多步操作 极简模式 | 仅双工具:持久 bash + str_replace_editor,无上下文压缩 创造模式 | 标准模式能力 + 运行时检查、插件实验、预设创作指导

一句话概括

普通回复是"思考的终点"——推理使命已完成,产出已交付,下一轮从头思考即可,回传纯属浪费;工具调用是"思考的中断"——模型话没说完,推理必须保留下来,才能在工具结果回来后接着想,这是协议要求,也是思考连续性的需要。

7.5 与缓存的关系


八、总结

  1. 插件化:DSH 采用"最小核心 loop + 事件驱动插件"架构。loop 是唯一含具体循环逻辑的插件,其余一切策略(压缩、重试、权限、子代理、持久化、UI)都是挂在其事件体系上的外围插件;Agent 预设(标准/PTC/极简/创造)本质是插件组装方案。

  2. 能力 seam 模式:以压缩为例——接口(dsh-compaction)与实现(dsh-compaction-basic)分离,接口只规定"做什么",实现决定"怎么做",两者可独立替换;替换入口是 preset 的 agent.cordis.yml

  3. 缓存:高命中率来自框架把请求前缀做"字节级稳定"(只追加历史、工具目录跨模式稳定、压缩回放前缀、排除噪声),命中主体是系统提示词 + 工具 schema + 历史消息前缀;命中由 DeepSeek 服务端前缀缓存自动完成,框架不主动"做"缓存,只是"省"出来的。

  4. 推理回传:思考模式下工具调用轮必须回传 reasoning_content(协议强制 + 思考连续性),普通回复轮丢弃推理(终态无需续接 + 省 token);DSH 适配器精确执行这条规则,并以"丢弃"策略优化成本与缓存。


文档基于 DeepSeek Harness 框架源码核实整理,主要来源:dsh-agent-loopdsh-compaction(-basic/-tool-result-pruner)dsh-llm-deepseekdsh-client-ui-trajectorydsh/config/agent-presets/* 等包的 README 与源码。

# DeepSeek Harness 插件化机制、缓存与推理回传解析

本文整理自一次关于 DeepSeek Harness(DSH)框架的深入问答,内容均基于框架源码(node_modules/@deepseek-ai/*)核实的事实,重点覆盖三大主题:
① Agent 插件化架构 ② KV 缓存命中机制 ③ 思考模式下的推理回传(reasoning passback)


目录

  1. [会话环境与背景](#一会话环境与背景)
  2. [Agent 预设:PTC 模式与其他内置模式](#二agent-预设ptc-模式与其他内置模式)
  3. [插件化架构:最小核心 + 事件驱动插件](#三插件化架构最小核心--事件驱动插件)
  4. [上下文压缩:一个典型的插件体系](#四上下文压缩一个典型的插件体系)
  5. [轨迹(Trajectory):会话过程的完整档案](#五轨迹trajectory会话过程的完整档案)
  6. [KV 缓存命中机制](#六kv-缓存命中机制)
  7. [推理回传(Reasoning Passback)](#七推理回传reasoning-passback)
  8. [总结](#八总结)

一、会话环境与背景

本次对话从环境认知开始,经历了 LightRAG 与知识图谱文档对比、PTC 模式探源、轨迹(trajectory)解析、插件架构(loop、compaction)、缓存命中机制,最后深入推理回传机制。本文聚焦后四个技术主题。


二、Agent 预设:PTC 模式与其他内置模式

2.1 预设即"插件组装"

DSH 官方定义:

预设(Agent preset)即一个会话的 Agent 所运行的插件组装——它的工具、提示词与能力。 复制一份既有预设改成自己的,或用「创造模式」让 Agent 帮你创建。

预设对"此后新建的会话生效,运行中的会话保持它开始时的预设"。

2.2 四种内置预设

预设 说明
标准模式 功能完整的编码 Agent:文件编辑、Shell、文件/网页检索、Skills、计划、目标、子代理、工作流
PTC 模式(Code mode) 标准模式全部能力 + Code Mode SDK:工具以异步绑定形式暴露,模型可写一段 TypeScript 程序(支持顶层 await/return)在一次运行中组合多步操作
极简模式 仅双工具:持久 bash + str_replace_editor,无上下文压缩
创造模式 标准模式能力 + 运行时检查、插件实验、预设创作指导

PTC 模式在中文 UI 中的全称是"PTC 模式",英文为 "Code mode";其核心是 @deepseek-ai/dsh-code-runtime(目前基于 Node worker 线程后端),对外通过 run_code 工具暴露。每个预设本质上是一套不同的插件组装方案


三、插件化架构:最小核心 + 事件驱动插件

3.1 loop 是一个插件——而且是"唯一不可替换的核心插件"

@deepseek-ai/dsh-agent-loop 的 package.json 描述:

"The concrete agent loop plugin for the DeepSeek Harness"

其 README 强调:

这是 harness 中唯一包含具体循环逻辑的包。 其他所有内容要么是抽象服务,要么是针对扩展点的插件:新行为应放入插件,而不是这里。

loop 的职责被刻意保持最小——调用模型、运行工具、重复(call model, run tools, repeat),并驱动**会话(session)→ 轮次(turn)→ 步骤(step)**的生命周期:

层面 职责
核心循环 调用模型 → 运行工具 → 重复
服务接口 AgentLoop(ctx 键 agentLoop),实现 AgentFactoryctx.agents.create()/resume()
inbox 机制 followup / steer / inject 三种输入队列,控制唤醒与下一步
并发 独占调用形成屏障,并行安全调用用有界滚动池(默认 10)
模型适配 ctx.llm.prepareCall()、适配器默认值标记、重试策略

3.2 一切策略能力都是外围插件

能力 实现方式
上下文压缩 插件监听 agent/pre-step(压力)、agent/request-error(溢出修复)
模型请求重试 dsh-llm-retry 监听 agent/request-error,退避重试
沙箱/权限/计划模式 tools/pre-execute 拒绝或询问、tools.guard() 策略、tools/post-execute 处理结果
子代理 在循环外部ctx.subagents 提供方用 ctx.agents.create() 创建 agent
持久化 监听 session/event 延后写入,session/flush 显式屏障
UI 监听 session/event(token 流、工具活动)+ agent/* 控制事件

架构哲学:loop 只提供事件体系(agent/*tools/*session/*),所有策略(目标、计划、子代理、权限、重试、压缩)都是挂在这副骨架上的外围插件。这正是 DSH 能自由组合出标准/PTC/极简/创造等预设的原因。


四、上下文压缩:一个典型的插件体系

4.1 "三包一体"的分层结构(capability seam 模式)

角色 职责
@deepseek-ai/dsh-compaction Service Definition(接口层) 定义 CompactionEngine 抽象服务(ctx.compaction)、compaction/* 事件、CompactionResult、工具配对边界 helper。只规定"压缩做什么"
@deepseek-ai/dsh-compaction-basic Service Provider(默认实现) ctx.tokenMeter 压力测量、阈值/保留尾部预算、llm.stream() 摘要、溢出恢复。规定"怎么做"
@deepseek-ai/dsh-command-compact Consumer 面向用户的 /compact 手动压缩命令
@deepseek-ai/dsh-compaction-tool-result-pruner 配套服务(可选) 无模型的工具结果剪枝:把超大的 tool/result 改写为"头部 + 省略标记 + 尾部"

关键设计:

4.2 压缩的组装位置(agent.cordis.yml)

压缩插件的组装点在每个 Agent preset 的 agent.cordis.yml。以标准模式为例:

# ── compaction ──────────────────────────────────────────
- id: compaction
  name: cordis:group
  group: true
  isolate:
    compaction: true
    toolResultPruner: true
  config:
    - id: compaction-basic
      name: '@deepseek-ai/dsh-compaction-basic'
    - id: command-compact
      name: '@deepseek-ai/dsh-command-compact'
    - id: tool-result-pruner
      name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
      config:
        thresholdChars: 8192
        headChars: 4096
        tailChars: 1024

4.3 如何替换压缩功能(三条路径)

路径 A:在预设配置里替换(推荐)

  1. Web GUI 的"Agent 预设"设置里复制一份预设;
  2. 编辑其 agent.cordis.ymlcompaction group:换 name 为自定义后端包名、调参或整体删除(极简模式即无压缩);
  3. 新建会话时选择该自定义预设。

compaction-basic 关键配置:

配置键 默认 含义
thresholdRatio 0.8 上下文用量达窗口 80% 触发压缩
retainRatio 0.16 保留近期表层 16% 逐字内容
retainTokens retainRatio 互斥的绝对保留预算
summarizationProvider / summarizationModel 指定摘要模型(默认复用当前路由)
maxTokens 8192 摘要输出上限
auto true 是否自动触发(false 则仅 /compact 手动)
modelPolicies [] {provider, model} 精确覆盖策略

路径 B:实现自己的压缩后端
继承 CompactionEngine,实现 compactIfNeeded(agent, trigger, signal)compactNow(agent, signal)compactRegion(start, end, agent, signal?),摘要直接走 ctx.llm.stream()(不是 loop 步骤),用 compactCheckpointSource(compactionId) 创建替换检查点,以插件形式注册为 ctx.compaction

路径 C:只换摘要策略(最轻量)
覆盖 BasicCompactionEngine 受保护的 summarize() 子类钩子——压力测量、保留策略、缩减验证全部由基类负责,只改"怎么总结"(模板摘要器或远程摘要器)。

4.4 压缩的表面约定(surface contract)


五、轨迹(Trajectory):会话过程的完整档案

5.1 记录类型与字段

轨迹记录有 7 种类型(TrajectoryCellKind):systemusercontextcompactedmessagetoolsubtool

每条记录包含:

字段 含义
#N 序号 + 摘要 记录索引与单行摘要(text / previewMarkdown
inputDetail 输入方向完整内容(对 tool 是调用参数,对 user 是消息原文)
outputDetail 输出方向完整内容(助手回复 / 工具结果)
thinkingDetail 模型的推理内容
sourceBlocks / outputBlocks 按模型消息顺序保留的原始内容块(文本、图片、tool-call 块)
schemaDetail 调用那一刻模型看到的工具 schema
assistantMetrics 首 token 时间(TTFT)、解码吞吐、token 用量
startedAt / timeSeconds 开始时间与耗时
isError / callId 失败标记与调用关联 ID

5.2 tool 部分的 payload 是什么

payload = argsRaw = 那次工具调用时模型实际传给工具的全部原始参数(未经加工、原样保留)。构建代码:

...node.call !== null ? { inputDetail: node.call.argsRaw } : {},   // payload(输入方向)
outputDetail: detailResult(node),                                    // 结果(输出方向)

UI 渲染逻辑:direction === "input" 显示 inputDetail(标签 "Payload"),direction === "output" 显示 outputDetail(标签 "Result")。未捕获时显示 "No payload captured" / "No result captured"。

举例:本次会话中调用 pwsh 工具时,轨迹里那条 tool 记录的 payload 就是 {"command": "Get-ChildItem ...", "description": "..."} 这样的原始调用参数。工具结果若是合法 JSON,轨迹面板会用 JSON 树展示。


六、KV 缓存命中机制

6.1 本质:DeepSeek 服务端前缀缓存

高缓存命中不是框架"主动命中"缓存,而是保证请求前缀稳定,让 DeepSeek 服务端的前缀缓存(prefix caching / KV cache)自动命中。框架只做了一件事:把"每次都要重新算的部分"压缩到最小,把"不变的部分"保持字节级稳定。

适配器把官方返回的命中 token 映射为轨迹面板的 cacheRead

// dsh-llm-deepseek/lib/index.js
const cacheRead = usage.prompt_tokens_details?.cached_tokens ?? usage.prompt_cache_hit_tokens;
inputTokens: usage.prompt_tokens - (cacheRead ?? 0),  // 计费输入 = 总输入 - 缓存命中

注意:DeepSeek 的 prompt_tokens 包含缓存命中部分,框架要把它减去才是真正的"新算力"输入。

6.2 缓存命中的主要内容(按体积排序)

  1. 系统提示词(最大头):DSH 系统提示词 + 会话 persona/工作规则,每次逐字相同
  2. 工具 schema:当前挂载的全部工具定义,工具目录不变即完全重复
  3. 历史消息前缀:早先轮次的 user 消息、assistant 回复、工具调用/结果
  4. 推理回传(条件性):仅含工具调用的 assistant 轮次才回传 reasoning_content

一句话:命中主体 = 系统提示词 + 工具目录 + 历史对话,即请求的"骨架部分";每次新增的是本轮新消息和工具结果,追加在可复用前缀之后。

6.3 DSH 做到高命中率的五条设计

  1. 历史严格"只追加"(append-only):loop 保留的响应块只追加到下一个请求尾部,前面的 token 一个不动;表层替换或压缩会从第一个被遮蔽 token 起使复用失效。
  2. 工具目录跨模式稳定:计划模式与正常模式不切换工具列表(即使某工具计划模式下不可用也照样列出)——"The tool catalog stays the same across modes for request-cache stability."
  3. 压缩时逐字回放前缀:摘要调用特意逐字回放系统提示词、工具与已遮蔽区域消息,将压缩指令作为最后一条 user 消息追加——"复用提供方的热前缀 cache,而非使它失效"。
  4. 排除噪声进历史:只有表层事件进入模型历史;流分片、生命周期边界等仅写入日志的事件被排除。
  5. 组装瀑布的字节级一致性:系统提示词、schema 的组装是确定性的,不掺入会变化的文本(如时间戳单独注入,不进系统提示词)。

6.4 什么会击穿缓存

事件 后果
切换 provider / model 完全不同的缓存域,全部失效
修改系统提示词、工具 schema、前缀 从第一个变化的 token 起失效
压缩替换(checkpoint) 从被遮蔽的第一个历史 token 起失效
工具结果被剪枝改写 从该结果起失效

结论:高命中率 = 框架把请求前缀做"稳定",命中是"省出来的"而非"做出来的"。长会话中 cacheRead 动辄几十万 token 而 inputTokens(新增计算)只有几千,正是因为绝大部分请求内容是重复发送的历史前缀。


七、推理回传(Reasoning Passback)

7.1 定义

推理回传 = 思考模式(thinking mode)下,携带工具调用的 assistant 轮次必须把模型的思考过程(reasoning_content)一并写入消息历史,作为后续对话上下文。

这是 DeepSeek 思考模式 API 的硬性协议要求(thinking-mode passback),不是可选优化。缺失时服务端返回 400 错误。多个主流框架都因此专门修复过:

7.2 DSH 适配器的实现规则

// dsh-llm-deepseek/lib/index.js serializeAssistant()
return {
  role: "assistant",
  content: text,
  // 只有"有工具调用 且 有推理内容"时才回传 reasoning_content
  ...toolCalls.length > 0 && reasoning.length > 0 ? { reasoning_content: reasoning } : {},
  ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
};
场景 是否回传推理 原因
有工具调用 + 有推理 ✅ 回传 思考模式 API 强制要求
有工具调用 + 无推理(推理关闭) ❌ 省略 没有可回传的内容
无工具调用(纯文本回复轮) ❌ 丢弃推理 终态不需要续接,省 token

7.3 为什么会有这个机制

① 协议硬约束:思考模式下,任何带 tool_calls 的 assistant 消息必须携带 reasoning_content,否则 400。这是服务端对消息格式的强制校验。

② 思考的"中断-延续"特性(深层原因):思考模式的推理 token 是自回归解码历史的一部分——模型"先思考、后回答",思考与答案是同一段生成流。

7.4 为什么普通步骤的推理无需回传

普通回复轮 工具调用轮
该轮状态 终态(话说完了) 中断态(等工具结果回来才能继续)
推理的作用 通往答案的思考,答案已在 content 发起调用的动机链,是后续解读工具结果的依据
后续是否依赖这段推理 ❌ 不依赖,下轮是新输入 ✅ 依赖,模型要"接上"自己的思考
省略推理的后果 无——答案完整,思考不参与续接 400 错误(协议)+ 思考断裂(语义)
回传的成本 白白膨胀历史、多付 token 必须支付,换取合法的多轮工具调用

一句话概括

普通回复是"思考的终点"——推理使命已完成,产出已交付,下一轮从头思考即可,回传纯属浪费;工具调用是"思考的中断"——模型话没说完,推理必须保留下来,才能在工具结果回来后接着想,这是协议要求,也是思考连续性的需要。

7.5 与缓存的关系


八、总结

  1. 插件化:DSH 采用"最小核心 loop + 事件驱动插件"架构。loop 是唯一含具体循环逻辑的插件,其余一切策略(压缩、重试、权限、子代理、持久化、UI)都是挂在其事件体系上的外围插件;Agent 预设(标准/PTC/极简/创造)本质是插件组装方案。

  2. 能力 seam 模式:以压缩为例——接口(dsh-compaction)与实现(dsh-compaction-basic)分离,接口只规定"做什么",实现决定"怎么做",两者可独立替换;替换入口是 preset 的 agent.cordis.yml

  3. 缓存:高命中率来自框架把请求前缀做"字节级稳定"(只追加历史、工具目录跨模式稳定、压缩回放前缀、排除噪声),命中主体是系统提示词 + 工具 schema + 历史消息前缀;命中由 DeepSeek 服务端前缀缓存自动完成,框架不主动"做"缓存,只是"省"出来的。

  4. 推理回传:思考模式下工具调用轮必须回传 reasoning_content(协议强制 + 思考连续性),普通回复轮丢弃推理(终态无需续接 + 省 token);DSH 适配器精确执行这条规则,并以"丢弃"策略优化成本与缓存。


文档基于 DeepSeek Harness 框架源码核实整理,主要来源:dsh-agent-loopdsh-compaction(-basic/-tool-result-pruner)dsh-llm-deepseekdsh-client-ui-trajectorydsh/config/agent-presets/* 等包的 README 与源码。