
《DeepSeek Harness 架构详解手册》全书面向零基础读者从 Cordis 插件地基讲到轮次流程、会话日志、工具流水线最后落到动手开发 Agent。本文把全书四个附录合在一起是一份可以随时回查的速查表。四个部分互不依赖按需翻阅即可附录 A扩展点速查表知道要做什么反查该挂在哪。附录 B核心 ctx 键速查表写服务名时对照避免拼错或搞混层级。附录 C新手最常见的十二个坑写完代码后自查一遍。附录 D资料来源与核对说明想知道某个说法的依据或跟同事口径不一致时查。其中附录 D 还专门记录了整理过程中发现的四处口径差异事件数量、默认端口、两种「上下文」、以及事件记录与进入派生历史的区别——这几处最容易在团队讨论时产生分歧。附录 A 扩展点速查表这张表回答一个问题「我想加 X应该挂在哪」它是按官方架构文档的「新行为的归属位置」表与实操手册的「功能→机制」映射表合并整理而成。A.1 按目标查机制我想做的事挂在哪添加模型提供方在ctx.llm上注册它的适配器添加面向模型的能力在ctx.tools上注册它的 schema 会自动加入提示词组装让某个会话拥有不同的能力集合组装一个 agent preset其中的服务行需要isolaterealm添加 shell 执行注册ctx.shell后端本地后端通过ctx.subprocessspawn 进程添加持久化终端执行注册ctx.terminals后端和dsh-tool-terminal添加用户命令在ctx.commands上注册它无需模型轮次即可分派管理后台任务在ctx.jobs上注册job_*工具读取或停止任务从外部 webhook 启动 Session在ctx.webhookRuntime上注册可信规则并挂载提供方适配器添加文件系统访问或策略注册ctx.fs提供方或监听fs/*事件限制所启动的进程使用ctx.sandbox后端消费方在启动进程前包装 argv拦截请求、工具或轮次使用相应的agent/*或tools/*事件agent/turn-stopping会停止轮次添加模型可见的上下文调用agent.inject()它会落到下一次获准的请求中添加 UI 或编辑器集成驱动ctx.agents并从session/event渲染添加 Web Client Chat 节点注册ConversationNodeDefinition keyed renderer添加持久会话状态扩展SessionEventMap从日志渲染和回放生成会话标题注册唯一的ctx.sessionTitle提供方管理同会话目标使用ctx.goals通过agent/*续跑在轮次边界 fork 会话ctx.agents.create({ sessionId, seed, meta: { parentSession, seedLength } })——只有经 agent-loop 发布的会话才会持久化在新后端存储会话基于共享的句柄脚手架实现SessionPersistencecreateopenstatlistexport将注册项限定到单个 agent使用该 agent 的agent.ctxA.2 按产品功能查插件机制产品功能插件机制钩子系统用户级 项目级agent/created、agent/pre-step、agent/request、tools/pre-execute、tools/post-execute、agent/turn-stopping上的监听器。dsh-hooks-claude-code/dsh-hooks-codex把钩子配置文件映射到这些扩展点/goalctx.goals管理持久状态dsh-goal-round-driver通过公共Agent调度同会话 Round/loop在turn/end会话事件上followup()下一次迭代或强制继续动态工作流ctx.workflowEngine PTC 工作流引擎 workflow工具排队消息 steering核心Agent.followup()/Agent.steer()上下文压缩自动 手动ctx.compactionseam dsh-compaction-basic。自动压力检查跑在串行agent/pre-step溢出恢复跑在agent/request-error手动调用方用同一个压缩服务系统提示词可配置性ctx.systemPrompt.section()支持排序与作用域局部覆盖AGENTS.md根目录一个读取该文件的 section 提供方AGENTS.md子目录按需触发 文件变更通知从 watcher 或工具结果监听器调用agent.inject()内置工具ctx.tools.register()schema 自动流入装配。dsh-tool-*系列bash、fs、web、subagent、todo是已交付的示例ToolSearch / 渐进式披露当可见集变化时替换一个作用域化的ctx.tools.restrict()注册工具截止时间 / 重试 / 指标用tools/execute包裹核心分发最终工具结果指标 / 审计 / 捕获用tools/result观察不可变的权威结果单调终端轮次策略从成功的终端工具调用ToolExecution.concludeTurn()子进程沙箱landlock / sandbox-exec通过dsh-bash-sandbox使用ctx.sandbox后端能力级别的拒绝用tools/pre-execute权限系统 / AskUserQuestion从tools/pre-execute返回ask并通过ctx.approval应答为普通用户提问注册一个独立的面向模型的 ask 工具Plan modedeepseek-ai/dsh-plan-mode落日志的plan/mode状态、plan:policy引导段、/plan入口、经用户评审的exit_plan_mode出口。强制约束留在独立的沙箱审批轴上subagent 委派ctx.subagents提供方注册表六个提供方dsh-tool-subagent向模型暴露一个已配置的提供方MCP每个服务器一个插件发现工具 →ctx.tools.register()skill技能section 工具注册调用时通过inject()注入 skill 内容记忆section 提供方 工具定时任务cron插件注册面向模型的调度工具定时器触发 → 空闲时followup(...)忙碌时inject()通知UIGUICLI 输出 JSONL监听agent/assistant-stream的实时 chunk并监听session/event的持久结算、边界与工具活动输入 →followup()遥测 / 可回放 tracesession/event→ JSONL回放 sessions.create(id, { seed })模型适配器通过registerAdapter注册LlmAdapter子类插件热重载每个注册都是一个ctx.effect所以随仓库提供的 HMR 直接生效A.3 所有事件一览按分发模式分组模式事件用途waterfallagent/pre-step拒绝或改写要进入步骤的消息。请求发出前的唯一拦截点waterfallagent/request替换冻结的调用配置换提供方模型推理强度采样参数waterfallagent/request-error处理一次失败的模型请求尝试。返回{kind:retry}触发重试waterfallllm/stream环绕每一次流式模型调用重试、回放、路由waterfalltools/pre-execute允许拒绝取消询问waterfalltools/execute环绕分派超时、重试、指标waterfalltools/post-execute接受替换阻止 / 附加下文waterfalltools/ptc-dispatch-log允许替换run_code子分派结果的日志副本内容waterfallsystem-prompt/assemble专家级整体装配变换。返回值具有权威性waterfallapproval/request一次性权限决策的分派serialagent/createdagent 已就绪可做每个 agent 的初始化。全部 await 完成前创建不算成功serialagent/turn-stopping轮次即将关闭的终局检查点parallelsession/flush等待的并行持久化检查点每个监听器都跑调用方 await 全部emitagent/status状态在idle⇄running之间切换emitagent/assistant-stream实时的助手流发布start、chunk、endemitagent/inbox/inserted·claimed·discarded跟踪单条消息的入队、领取、丢弃emitagent/disposed·agent/erroragent 离开注册表 / 步骤或轮次出错emitsession/created·session/disposed会话发布与离开emitsession/event提交后的追加通知源。可回放数据都从这里读emittools/change·tools/result工具集变化 / 观察冻结的最终结果emitsystem-prompt/change·llm/adapters-updated提示词提供方变化 / 提供方拓扑变化emitapi-session/*会话列表的活动、加入、移除、状态、错误emitagent-preset/selected某个会话向它的持久日志提交了不同的 agent preset附录 B 核心 ctx 键速查表写插件时你最常做的事就是在某个ctx键上注册东西。这张表按「你关心的领域」分组列出最常用的键。完整清单见官方的能力图。ctx 键角色你会用它做什么核心四件套ctx.agentscore创建恢复查找 agent传播发起方currentInitiator/withInitiatorctx.agentLoopbundle唯一的具体循环实现。扩展包不要依赖它依赖ctx.agentsctx.sessionscore创建会话、注册消息投影、fork、flush 检查点ctx.toolscore注册工具、设置守卫、限制工具、按作用域查询 schemactx.systemPromptcore注册提示词段落、动态上下文、工具 schema 提供方、变量ctx.llmseam注册模型适配器直接发起一次模型调用查询模型能力执行环境ctx.fsseam文件系统读写本地沙箱远程ctx.subprocessseam启动进程Bash、PTY、LSP、外部 subagent 都靠它ctx.shellseam面向模型的 shell 执行后端ctx.terminalsseam持久化的交互式终端ctx.sandboxseam进程沙箱包装即将执行的 argvctx.sandboxPolicycore部署默认沙箱模式与工作区根目录ctx.lspseam语言服务导航只有四种标准化操作ctx.sshcore一条经过认证的 OpenSSH 连接及其远端提供方安全与审批ctx.approvalseam一次性权限决策的分派与应答ctx.permissionPresetscore用户可见的权限预设切换ctx.credentialsseam机密信息的引用。配置只携带引用实际值归提供方所有消费方按操作解析所以轮换的凭据会在下一次请求就生效ctx.authorizationseam授权流程注册怎么拿到某份凭据ctx.deepseekAccountseamDeepSeek 账号。UI 使用方只接收不含 token 的状态会话数据ctx.sessionPersistenceseam把会话事件持久化到磁盘ctx.sessionProjectionscore注册状态折叠单元读单个类型化状态ctx.sessionProjectionCachecore按会话持久保存投影检查点加速恢复ctx.sessionQueryseam会话的读取、过滤、追踪、搜索ctx.sessionTitleseam会话标题生成ctx.storage/ctx.storageDomainseam / core非会话存储的中枢类型化持久状态ctx.attachmentsseam持久的二进制附件存储图片、文件ctx.spillStoreseam过大的工具文本的暂存与定位协作与外部世界ctx.subagentsseam子 agent 的提供方注册与延续编排ctx.agentTeamscore实验性多 agent 协作roster、mailbox、任务 DAGctx.jobsseam后台任务的注册与控制ctx.webseamweb 搜索与抓取的提供方注册ctx.skillsseam技能目录ctx.mcpResourcesseamMCP 资源访问ctx.browserUse/ctx.computerUseseam浏览器操作桌面自动化ctx.webhookRuntimecore外部 webhook 触发会话创建ctx.schedulecore定时消息ctx.commandscore面向人的命令无需模型轮次ctx.userQuestionsseam工具向人提问的通道ctx.planModecore计划模式的协作状态ctx.goalscore同会话目标应用与界面ctx.agentPresetscore按会话的 agent 组合YAML presetctx.webServercore注册 HTTP 路由ctx.clientModulescore客户端插件图ctx.connectioncore浏览器认证与共享 HTTP 请求分发ctx.settingscore插件配置表单ctx.configEditorcore在应用文件锁与 HMR 队列下持久化 profile 配置 patchctx.pluginManagercore当前 profile 的插件与组合包管理ctx.otel/ctx.sessionTelemetryservice / seam共享的遥测上报通道附录 C 新手最常见的十二个坑这一章是按「错误认知 → 正确认知」的方式整理的。这些坑大多来自「用别的框架的经验硬套过来」而不是来自不会写代码。#常见错误认知正确认知1「我应该去找核心抽象层基类」这里没有特权内核。你要找的是挂载点——某个ctx键或某个事件。见第 1、10 章2「patch 是深度合并我只写要改的字段」patch 按 id 定位后整体替换config。你必须把想保留的字段全部重述。见第 2 章3「我把系统提示词清空了但模型还记得旧指令」空渲染文本会清除所有生效的系统节点。如果旧指令还在起作用它大概不在系统提示词里——检查 user 消息和 skill 注入。见第 5 章4「往内存里的 messages 数组塞东西模型就能看到」模型历史是从日志派生的。要写事件或者调用agent.inject()。见第 4 章5「状态是 running 说明它正在处理我这条消息」running跨越整个驱动器排空区间可能包含多个轮次。要知道单条消息的进度看 inbox 通知和轮次事件。见第 3 章6「我想阻止轮次结束就返回一个 veto 值」agent/turn-stopping是 serial没有next()。想阻止就 steer 一条消息让机器重新读 inbox。见第 3 章7「并发安全默认应该是开的吧」默认是exclusive独占而且 fail-closed。想并行要主动返回严格true。见第 6 章8「我把结果内容替换掉了就算保密了」内容替换是展示策略。程序仍然能拿到value。要保密就用block或替换value。见第 6 章9「命令返回非零所以工具该抛异常」非零退出是正常的领域结果应该作为值返回由渲染器解释。**只有基础设施故障才抛异常。**见第 6 章10「重试应该在适配器里做」一次适配器调用 一次提供方尝试。适配器禁用库重试重试是 agent 层的职责。见第 7 章11「currentInitiator()有值所以这次调用是被授权的」归因不等于授权。发起方方法只提供同进程内的因果归因。授权走审批 seam。见第 9 章12「我加了一个新事件类型读取时应该跳过不认识的事件」默认是必需遇到不认识的、又没有ignorable标记的事件必须拒绝重建。**宁可多报一次错也不要静默恢复出一个被掏空的会话。**见第 4 章附录 D 资料来源与核对说明这份手册的内容全部来自官方仓库的文档。这一章说明资料来源、范围边界以及我在整理过程中发现并处理的几处需要留意的地方。D.1 主要资料来源文档本手册用它来支撑docs/architecture.zh.md整本书的骨架Cordis 定位、profile 与组合包、核心包表、事件三域、轮次流程伪代码、会话日志、能力 seam、归属位置表docs/cordis-primer.zh.md第 1 章五个核心概念、五种分发模式、waterfall 语义、实践规则docs/cordis-tutorial/index.zh.md第 10 章七章动手教程的路径与准备工作docs/agent-lifecycle.zh.md第 3 章轮次与步骤的时序细节、失败与重试的处理位置docs/tool-execution-pipeline.zh.md第 6 章工具流水线的完整关卡顺序、PTC 与上下文附加docs/capability-seams.zh.md第 8 章与附录 Bseam 列表、角色分类、各键的职责与消费方docs/subsystems/core.zh.md第 3、4 章Agent 句柄与全部方法、inbox、取消语义、两个类型模式、会话事件清单docs/subsystems/session.zh.md第 4 章事件表全字段、surface 与 surfaceOp、派生规则、持久化约定、forkdocs/subsystems/tools.zh.md第 6 章ToolDefinition 全字段、schema DSL、执行类型、决策类型、UI 卡片词汇docs/subsystems/system-prompt.zh.md第 5 章PromptSection 全字段、三种更新方式、工具提供方结果docs/subsystems/llm-streaming.zh.md第 7 章内容块、StreamChunk、BlockAssembler、适配器约定、重试策略、TokenUsagedocs/subsystems/scope.zh.md第 9 章ScopeKey、Scoped、Scope、ScopedLayers 与容器原语docs/cookbook/extension-cookbook.zh.md第 1 章的门禁示例、第 10 章的实操模式、附录 A 的功能映射表docs/cookbook/adding-a-tool.zh.md第 6、10 章工具约定、PTC 设计建议、后台任务、UI 展示规则docs/user/develop/basic/tool.zh.md第 10 章最小可运行的工具示例与--patch开发方式packages/boot/app-boot/README.zh.md第 2 章启动五步、失败模式表、profile 与 runtime resolutionREADME.zh.md封面信息、运行方式、项目状态与许可D.2 核对中发现并处理的四处地方为了让这份手册不把读者带进沟里以下几处我在整理时专门做了处理并把结论写在这里。#发现的问题处理方式1**会话事件的数量存在两种口径。**核心包文档写「十三种核心事件变体」并列出十三项而会话子系统的事件表里还登记了developer/message以及由插件合并扩展的compaction/*、hook/*等第 4 章明确采用「核心十三种」的口径并单独用提示框解释了两种数字的关系一个说「核心」一个说「当前全部」避免读者以为文档自相矛盾2**两个默认端口容易混。**README 里的 Web 默认地址是127.0.0.1:3080而桌面应用文档里的默认端口是19387第 2 章专门加了一个提示框把两个数字并列说明并指出 19387 是桌面端且可被 profile 覆盖避免读者看到 19387 时误判为配置错误3「上下文」一词在此框架中有两个完全不同的含义。ctxContext指插件共用的服务容器而contextWindow指模型能处理的 token 上限术语表第 11 章为这两个词分别立条并在 Context 条目下明确写出「不是『语言模型的上下文窗口』」。第 7 章也再做了一次区分4**assistant/message与assistant/attempt的「是否进入模型历史」表述容易误读。**文档说法是后者「不添加模型历史」前者「内容为空的也会跳过」第 3 章用一张两列表把两者并排对比并特别标注「记录事件」与「进入派生历史」是两件独立的事——空内容的 assistant 消息仍然会记录只是不进派生历史D.3 范围边界说明一下这份手册没有做什么以免读者产生错误的期待**没有逐字段抄录所有生成型文档。**官方仓库里有一批由脚本生成的参考页config-catalog、persistence-catalog、各子系统的cordis-surface代码块。一个包里面就可能有几十页 JSDoc 原文。这些属于「查」而不是「读」本手册只在需要说明机制时引用其结论没有整体搬运。**没有覆盖每一个实验性包。**实验性的浏览器操作、计算机操作、语音识别、Python 版 PTC 运行时等只在 seam 列表里点到没有展开。**没有给出可复制的完整插件工程。**本手册的代码片段用于说明「为什么这么写」很多省略了 import 与辅助实现——官方也明确说了这一点。要跑起来请走第 10 章的路径并参考官方教程。**没有承诺长期有效。**项目处于开发者预览阶段官方明确写着「未来将出现破坏兼容性的变更」。本手册描述的是这组文档所记录的架构契约与设计取舍——这部分相对稳定具体字段名、命令参数请以你手上的代码为准。D.4 一份实用的一句话总结这套架构只讲了一件事把「行为」和「策略」都变成可以挂载、可以替换、可以撤销的插件然后用一条仅追加的日志保证「发生过什么」永远可查、可重建、可回放。学它的顺序也应该是这个顺序先接受「日志是唯一真源」再接受「一切皆插件」最后学会问「这件事该挂在哪个扩展点上」。这三步走完剩下的都是查表。使用建议如果你只想把一张纸贴在显示器边上我建议是附录 C 的十二个坑因为它覆盖面最广几乎每一条都对应着手册某一章里反复强调过、但在动手时又特别容易忘的点。四份表都只是速查想看某个为什么这么设计回到正文对应的章节即可那里有完整解释与配图。内容整理自 DeepSeek Harness 官方仓库docs/architecture.zh.md及其引用的全部子系统、教程、实操手册与核心包文档。官方项目处于开发者预览阶段具体字段与命令请以你手上的代码为准。