DeepSeek Harness 的 Harness 到底做了什么
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
DeepSeek Harness 解决的核心问题,是多轮模型调用、工具执行与会话状态之间的协调:输入何时进入请求,工具结果如何写回历史,请求失败后从哪里重试,上下文压缩后保留哪些信息,以及任务中断后能够恢复到什么状态。 围绕这些问题,框架将运行过程拆分为插件装配、回合驱动、会话日志、工具管道和异常处理。分析其架构的关键,在于各部分的状态边界,以及这些边界提供的保证与限制。 本篇文章限定在提交 477b4f4205(2026 年 9 月 25 日)对应的实现。 1. 插件装配插件是 DeepSeek Harness 的核心能力,插件的配置决定 Agent 的运行能力。 DeepSeek Harness 通过 Cordis 插件组织运行能力。Cordis 提供 Context、Service、Plugin 和 Event 等抽象,插件通过依赖注入与事件系统协作,并由框架管理生命周期。 LLM 服务、Session、Agent、AgentLoop 和工具注册表等基础组件,由 bundle 统一挂载。启动时,dsh 以 profile 为入口加载配置,按 id 定位配置行,并替换对应的整段 config。 这里的配置语义是整段替换,而非字段级合并。覆盖某个组件的配置时,原配置中未被保留的字段也可能随之消失。 插件装配因此直接影响 Agent 的实际行为:模型服务是否可用、哪些工具被注册、哪些事件处理器参与执行,都取决于最终加载的插件与配置。仓库包含某项能力,并不等于当前运行实例已经启用该能力。 这种设计便于替换组件和组合能力,但也让执行逻辑分布在多个插件中。分析一次请求的行为,需要同时查看核心循环、插件注册关系和最终生效的配置。 2. 核心循环Agent 循环是 Agent 的核心逻辑,其主要区分回合、步骤与请求重试。 从实际的工作逻辑上来看,agent-loop 负责驱动模型与工具之间的循环。其主要执行路径包括:
理解这条路径,需要分三个层次:
因此,step 不能简单等同于一次网络请求。重试可能产生多次请求尝试,但不应重复消费输入或重复提交用户消息。 Agent 维护 next-turn 和 next-step 两个队列,分别承接下一回合与下一步的输入。队列修改以 agent/inbox/spliced 事件写入 Session,待处理输入可以从日志投影恢复。 这一设计区分了「系统已经收到消息」和「模型已经消费消息」。 执行过程中到达的补充要求,需要在相应边界进入后续请求。它不能自动改变已经发出的模型请求,也不能撤销已经发生的工具副作用。输入排队与执行取消因此属于不同机制。 将队列变化写入日志,还能避免恢复时只找回聊天记录,却丢失尚未处理的输入。 3. SessionSession 机制实现了运行记录与模型历史分离。 Session 被设计为只追加的事件日志,事件通过递增序列号确定顺序,以 type 区分类型,以 body 保存内容。 日志不仅记录用户与 assistant 消息,也记录请求失败、输入队列变化、工具执行和压缩过程等运行事实。 但日志中存在的事件,不一定进入模型上下文。 真正发送给模型的 messages,由 Session 的 surface 通过 deriveMessages() 重建,再冻结为不可变请求。只有进入 surface 的消息事件参与历史投影;assistant/attempt 等运行记录不会自动成为模型消息。 这一分离有两个作用:
Session 的 append 还会检查 JSON 可序列化性、事件规则及 surface 替换的合法性,以减少无法持久化或无法正确投影的数据进入日志。 日志恢复不等于外部动作回滚 只追加日志为审计与状态重建提供了基础,但不能单独保证任意中断点都能无损恢复。 例如,工具已经修改文件,但结果尚未写入 Session 时进程退出,外部环境与日志之间就可能出现状态差异。恢复日志可以还原已提交的记录,却不能仅凭「缺少结果」判断工具没有执行。 因此,恢复能力需要区分:
后者还依赖工具的幂等性、状态检查能力或额外的事务机制,不能仅由 Session 的追加式设计推导出来。 4. 工具管道工具管道实现了从模型意图到受控执行。 工具注册表只向模型暴露 name、description、parameters 等白名单字段。执行函数、超时设置和并发属性保留在运行时。 这将模型侧的工具描述与运行时的执行控制分开:模型负责提出调用,框架负责判断调用是否可执行,以及如何执行。 一次工具调用依次经过:
权限检查、执行包装和结果处理因而拥有独立的介入位置,不必全部写进工具函数。 并发执行与顺序提交分离 同一条 assistant 消息可能提出多个工具调用。调度器通过工具的 isConcurrencySafe 属性分类:
并发是显式声明的能力,未声明安全的工具不会默认并行执行。 工具本体可以并发,但准备、后处理、tool/result 写入及附加 context 入队,按模型调用顺序提交。这样可以避免工具完成时间的随机性直接改变会话中的结果顺序。 代价是可能出现等待:后面的工具即使先完成,也需要等待前面的调用提交。并发能够缩短部分执行时间,却不保证结果可以立即进入历史;提前完成的结果还可能需要暂存。 此外,提交顺序稳定不等于外部副作用确定。并发工具是否真正安全,仍取决于它们是否访问共享状态、是否存在执行依赖,以及并发声明是否准确。 5. 安全隔离DSH 在实现上让审批与执行限制分别生效,以实现安全隔离。 Harness 的沙箱模式包括: 策略涉及文件路径权限、命令执行限制和权限提升。工具可以通过 justification 与 sandbox_permissions 请求提升权限,再由 approval 机制处理审批。 基础 bundle 默认挂载 workspace-write 文件沙箱与 ask 审批策略;sandbox-policy 将当前文件操作模式解析给实际后端。 这一结构包含三个不同层次:
安全边界最终取决于策略配置与实际后端的共同约束,而不只是沙箱模式的名称。 6. 异常收敛异常是应用中很常见的东西,也是 Harness 的重点处理对象。 DSH 通过重试、压缩与取消各自处理不同问题。 6.1 请求重试通过请求重试来保留失败记录,避免重复提交输入。 模型请求失败后,系统先写入 assistant/attempt,再交给 agent/request-error 瀑布链处理。 llm-retry 根据适配器提供的 retry policy,判断错误类型、重试次数与退避方式。计划重试与实际启动分别记录为 llm/retry 和 llm/retry-started。 重试在同一个 step 中重新准备请求,不重复提交首次用户消息。这一边界避免了网络层重试演变成会话层的重复输入。 分别记录重试计划与启动,也使日志能够区分“决定重试”与“已经开始下一次尝试”。 6.2 上下文压缩上下文压缩实现了替换可见历史,保留原始事件。 自动压缩在 agent/pre-step 检测上下文压力,并记录:
随后,系统将选中的连续历史区间替换为一个 checkpoint 用户消息。 这里发生的是 surface replace:模型可见历史缩短,原始日志仍然保留。因此,压缩减少的是请求上下文,不等于同步减少持久化存储。 压缩也引入了信息损失的可能。原始约束即使仍在日志中,只要没有进入摘要或剩余 surface,后续模型就无法直接使用。压缩是否有效,除了看上下文长度,还取决于任务目标、限制条件和未完成事项是否得到保留。 6.3 取消通过取消来传递停止信号,而非撤销既有结果。 AbortSignal 贯穿回合、请求和工具,使取消信号能够沿执行链传递。 但信号传递不等于立即停止所有动作。工具是否及时退出,取决于其是否检查并响应取消;已经完成的文件写入或远端操作,也不会因 AbortSignal 自动回滚。 取消机制提供的是停止继续执行的控制路径,外部副作用的撤销仍需要独立实现。 7. 小结DSH 的 Harness 实际上是一种架构的取舍,其取舍考量的是可追溯性与运行成本。 如下的机制共同形成了 DeepSeek Harness 的主要工程取舍:
DeepSeek Harness 的核心价值,是将 Agent 执行中的关键状态显式化:输入有队列,执行有边界,请求有可见历史,工具有调度与审批,失败有独立的处理路径。 这些机制使多轮任务能够被追踪、检查和恢复,同时也明确了框架的能力边界:日志恢复不能替代副作用确认,顺序提交不能替代并发安全,权限审批不能替代环境隔离,上下文压缩也不能保证信息无损。 以上。 阅读原文:点击这里 该文章在 2026/11/3 10:34:13 编辑过 |
关键字查询
相关文章
正在查询... |