Files
deepseek-harness/docs/architecture.zh.md
Yichen Jiang 52607cab69 docs(agent-presets): bring the note and the architecture map up to what shipped
The Agent Note was written when only the seam existed and never caught up.
Rewritten in place, per the implemented-note contract, with the four facts the
later work established:

- a preset file is an INPUT: `EntryTree.write()` persists a tree whenever the
  Loader thinks the config changed, and a self-disposing plugin is enough, so
  the inherited behaviour truncates a shipped preset to `[]` the first time a
  session ends
- a plugin that looks itself up in the global registry breaks inside a preset,
  because `register()` files into the calling context's scope — the general
  rule behind the `dsh-tool-skill` fix
- an entry-local `isolate` realm is invisible to the agent's own scope too, not
  only to the host, which is what makes a preset's registry that agent's own
  and also why a consumer left outside the group silently contributes nothing
- switching is blank-only, and why it swaps the subtree rather than the session

`docs/architecture.md` gains an Agent Presets section: the map has to carry a
new architectural concept or it is wrong, and the root layout gains the group.

Both budget ceilings are raised rather than the content cut. `AGENTS.md` sat at
1774/1775 — one word of room, already far under the 5% headroom the standard
asks for — so no group line could be added at all; `architecture.md` was in the
same shape. Raising restores headroom instead of encoding "the map may not grow".
2026-08-07 00:40:43 +08:00

19 KiB
Raw Blame History

DeepSeek Harness 架构

English | 中文

DeepSeek Harness SDK 使用 Cordis一切皆插件,循环也不例外。

概览

每个 harness 都是 Cordis 上下文各包package贡献服务、类型化事件和可释放的注册项。packages/core/ 汇集默认流程;各项功能仍以插件形式存在。

默认服务

ctx 键 职责
dsh-scope 作用域上下文注册项与共享层存储(库)
ctx.sessions dsh-session 内存中的事件溯源会话
ctx.systemPrompt dsh-system-prompt 有序的提示词片段、工具 schema 和变量
ctx.tools dsh-tools 工具注册表和执行流水线
ctx.agents dsh-agent 活跃 agent智能体、委托创建、agent/* 事件、进程内发起方作用域
ctx.agentLoop dsh-agent-loop 实体 Agent 驱动器

功能服务

ctx 键 包族 职责
ctx.llm llm/ 适配器注册表和模型流式调用
ctx.tokenMeter llm/token-meter 感知回放的单实例请求压力与表面压力
ctx.bash bash/ 前台和后台命令执行
ctx.subprocess subprocess/ 供 bash、LSP 与 ACP subagent 后端使用的受管子进程树
ctx.pty pty/ 按 owner 隔离的持久化终端会话
ctx.sandbox sandbox/ 通过 argv 包装和逐调用策略限制同一执行环境内的进程
ctx.sandboxPolicy sandbox/ 共享沙箱策略归属点
ctx.codeRuntime code-runtime/ 执行模型编写的程序
ctx.fs fs/ 文件系统提供方原语和策略事件
ctx.lsp lsp/ 语义导航注册表
ctx.skills skill/ skill技能提供方注册表和渐进式披露
ctx.web web/ 搜索与抓取提供方注册表
ctx.compactctx.toolResultPrune compact//compact-tool-result-prune 摘要压缩compaction和可选的无模型结果裁剪
ctx.subagents subagent/ 具名委托提供方
ctx.planMode plan/ 落日志的 plan 协作状态
ctx.tasks tasks/ 后台任务注册表和通用 task_* 控制
ctx.workflows workflow/ 脚本驱动的多 agent 编排
ctx.goals goal/ 持久化的同会话目标
ctx.sessionPersistence session-persistence/ 会话日志的持久化存储
ctx.sessionQuery session-query/ 基于 SQLite 全文搜索的实时优先精确检索/过滤/追踪、经工作区授权的模型工具
ctx.sessionTitle session-title/ 基于日志的回退标题和单个可选异步提供方
ctx.settings settings/ 按插件划分的用户设置命名空间,分层叠加在装配条目之上
ctx.credentials credentials/ 具名密钥引用,按操作解析,绝不内联进配置
ctx.directoryPicker host/directory-picker GUI 宿主目录选取(nativebrowse 交互)
ctx.typert typert/registry 生成的包反射和实时 Zod schema 的运行时注册表
ctx.invariants support/invariants 按包名筛选包自有运行时检查的注册表

事件

事件就是服务的扩展 API目录生产方与消费方映射)。

事件域

  • 会话事件是通过 session/event 发出的持久日志事实。
  • Agent 事件携带活跃 Agent,用于 inbox、步骤、状态、请求、验证和续跑。
  • 功能事件无需导入循环即可附加策略和适配器。

拦截语义

waterfall瀑布式事件是环绕中间件监听器通过 next() 委托;不调用它而直接返回会否决或接管(语义)。

默认循环生命周期

会话采用仅追加方式。一个轮次领取一条已排队的后续消息,等待前一轮次的检查点,并可与其共用 running 区间(决策);注入不领取输入。一个步骤包含一次模型请求及其工具。新建与持久化恢复会先取得精确的未发布 SessionPreparation;只有基于该 Session 的私有设置准备完毕后,系统才会发布 agent 与会话(决策)。时序中的引号标记持久事件。

创建时若未提供 id流程会生成 <config-id>-session-<uuid>sessionId 用于恢复或创建会话,而 resumeSessionId 要求已有历史。恢复流程在发布前还原沿袭关系和委托深度;初始化失败会发出 agent-loop/config-start-failed

轮次流程

choose declarative identity and acquire fresh/restored SessionPreparation
  -> prepare private agent.ctx around exact Session -> await unpublished setup -> invoke optional synchronous setup commit
  -> enter session + agent -> session/created -> agent/created
  -> enable driving -> agent/session-start(source) -> start driver
forever:
  waking inbox insertion starts the driver before send returns
  -> emit agent/status(running) if starting an interval
  -> 'turn/start'
  claim next-step input plus one next-turn message
  -> emit agent/inbox/claimed({ message, turn }) for each claimed message
  -> agent/pre-step({ agent, messages, turn, step, signal })
    reject, empty input, cancellation, or listener failure
      -> the claimed batch stays removed; close the no-step turn; stop the driver
    enter -> step loop:
      'step/start'
      append the returned batch as separate 'user/message' events
      assemble ordered prompt and tool schemas -> snapshot derived messages
      agent/request (config only) -> prepare adapter defaults/provenance + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
      'assistant/chunk'
      'assistant/message'
      schedule tool calls by ctx.tools.executionMode:
        exclusive -> barrier
        parallel -> rolling pool, <= maxParallelToolCalls; reclassify at start
        start -> 'tool/call' -> tools/pre-execute -> concurrent tools/execute
        model-order result -> ordered tools/post-execute -> 'tool/result'
      'step/end'
      tools owe another request or next-step inbox is nonempty
        -> claim -> agent/pre-step -> append entered batch -> continue
      otherwise agent/turn-stopping -> re-check the next-step inbox
    'turn/end'
  start the next waking queued message, or emit agent/status(idle)

idle inject:
  queue non-waking next-step context
  leave it pending until followup or steer wakes the driver

每个步骤都会组装有序的提示词片段、工具 schema 和变量;未知引用会使该轮次失败。dsh-system-prompt 负责身份和角色设定;循环提供 providermodelcwd提示词归属)。

inject() 将不会唤醒驱动器的上下文排入 next-step;空闲驱动器会让它保持待处理,直至 followup()steer() 唤醒。工具执行后的 additionalContexts 使用同一个 inbox。agent/pre-step 的 payload 携带独占的已领取批次,以及即将使用的轮次、步骤和信号。拒绝则不进入步骤;进入则提供在 step/start 后追加的完整批次。空的工具续跑仍会经过 waterfall其最终值一次性结算所有改写。

裁剪先于摘要;溢出重试必须取得持久进展。agent/request-error 可以授权使用冻结提示词进行同步骤重试;取消优先。适配器的 retryPolicy 使 normal mode 保持有界always mode 则在专门恢复后重试(压缩重试基础提供方策略)。精确事件顺序由生成的 agent 生命周期定义队列、steering、重试与取消机制由 agent-loop README定义。

失败边界

适配器选择、分发与迭代失败会成为 error 或 aborted 类型的终止 finish 分片。agent/request-error 接收请求坐标、标准化 LlmFailure、可用的重试策略和信号middleware 与消费方错误仍在恢复之外。失败分片既不提交消息,也不提交工具调用。

其他故障使用 agent/error;取消和资源释放优先于恢复。在提交请求头之前,轮次信号会取消功能准备;尚未分派的工具会得到合成的 tool/call/ABORTED_BEFORE_DISPATCH 对。实际生效的 cancel(cause) 会在清空队列和中止前报告原因;空闲调用不发事件。持久化层以 aborted 区分取消,以 disposed 区分会等待完全停稳的拆卸(决策)。

轮次和步骤事件均位于轮次边界内loop 只会在轮次内从进入步骤的批次追加 user/message。轮次会在首次领取与 pre-step 之前打开,因此拒绝、空输入、取消或失败会关闭一个不包含任何步骤事件的持久轮次。独立的 compact/* { turn: null } 事件不占用轮次,其锁定时刻标记可以与 inbox splice 交错。重新加载会为中断的轮次合成结束事件;session/end-seed 区分陈旧的压缩遗留项与活跃锁。关闭后仅由 agent/error 报告故障。每个轮次有一个 TurnEndReason

Agent 句柄

ctx.agents 拥有 agent 并返回 AgentHandle { agent, dispose() }。插件使用 send(),或使用其 followup()steer()inject() 预设。cancel()whenIdle() 控制生命周期,需等待完成的资源释放则负责拆卸。后续消息的 MessageId 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识提示词输出或轮次结束;只有完整活动区间的所有方才能将其概括为一次运行结果(决策)。

Agent 作用域

每个 agent 都拥有作用域化的 agent.ctx;共享存储会将其工具、提示词和命令条目叠加到全局条目之上,同时保留各领域视图(决策)。作用域监听器会过滤分派;贡献都会在撤销时等待清理完成。CreateAgentOptions.setup(agentCtx) 在发布前完成组合。类型化解析器从合并后的 EventsscopeTarget 推导载体检查(语义门禁)。详情见 agent 作用域subagent 组合AgentLoopctx.agents.withInitiator() 内运行;私有编排会派生 agent.session但轮次、步骤、信号、cwd 和权限仍保持显式(决策)。

状态

会话日志

会话日志是权威依据。deriveMessages() 投影出模型历史;原始 assistant/chunk 事件保证回放和 UI 保真。fork、恢复、transcript文本记录渲染、遥测和持久化均派生自该事件流。

模型可见 ⟺ 已记录:在 step/start 进入的消息加上折叠后的 request/header 可以重建每个请求。该 header 会标记适配器默认值,使后续提议丢弃这些值并重新解析路由,同时不丢失显式设置。request/context 会在路由变化时另行记录与注册项绑定的提供方、模型及容量元数据;它不参与请求重建或 header 相等性判断。dsh-agent-loop/invariant 通过 ctx.invariants 断言可重建性(可重建性)。

持久性由插件负责。后端会尽快排空同步的 session/event 通知。session/flush 位于请求与顶层工具分发之前,并在 turn/end 之后、另一个轮次或空闲状态之前执行。SessionPersistence 存储事件和 header 元数据JSONL 默认采用带校验和的 ZstandardSQLite 遵循同一契约(决策)。

在轮次之间,事件所有方通过 Session 追加纯日志事件,仅为持久性而刷写。session/title 需要尽快持久化与生命周期排空;手动压缩会在操作完成前 flush 其标记对。标题工作绝不延迟响应;最新标题按后写覆盖并携带来源信息。标题记录是可继承的 fork 边界(决策)。

模型内容

消息使用从可合并扩展的 ContentBlockMap 派生的类型化块;同一模式也为 MessageSourceFinishReasonTurnTriggerTurnEndReason 定义类型。新增块会协调适配器、UI、压缩、token 计量和持久化;回放计量见 token-meter.md

流式输出使用原始分片和 BlockAssembler。每次 LlmAdapter.stream() 调用代表一次提供方尝试;适配器报告标准化的故障事实,负责处理的 agent/request-error 插件会返回重试动作。循环会记录分片、成功结果的来源信息和回放状态。远程适配器使用逐次读取空闲看门狗。回放仅通过共用的适配器实例跨路由传递(契约)。

扩展与组合

功能模式

可替换功能通常具有接口/实现/消费方三层服务和事件、后端、面向模型的工具和提示词。Bash 是参考实现;功能图映射了每个包族。

例外情况包括 LLM大语言模型合并接口和消费方、文件系统整合策略、web 使用注册表、skill 和 subagent 使用具名提供方。subagent 可以通过 spawn 创建全新实例、fork 一个已完成轮次的前缀,或使用 ACPAgent Client Protocol子 agentsubagent.md)。

dsh-workspace-context 在第一次 agent/pre-step 组合基线并将它折入最终进入的批次、紧随已领取的直接提示词之后使其与直接提示词一同抵达第一次请求reject 则将它留在 next-step inbox。工具执行后投影的文件系统变更也会折入下一次进入步骤的 pre-step而不会另外创建稍后的纯上下文步骤决策)。dsh-paths 负责共享路径。

组合包与应用

dsh-agent-spine-demo 组合一套主干和可选目标。应用包负责 CLI命令行界面、ACP 自动化入口和 JSON-RPC 入口(READMEacp/ui/)。dsh-jsonrpc-agent 启动外部 cordis.ymlPython SDK 在配置缺失时提供默认项(Python SDK)。轻量部署使用可替换后端和可选工具(examples/可运行接线图谱)。

Agent Preset

部署可为每个会话分别组装面向模型的插件集合。agent preset 是一个含 agent.cordis.yml 的目录,在 setup(agentCtx) 期间作为 include 子树挂到该 agent 的 scope 之下,其工具与提示词注册因而归档进该 agent 的分层并随之卸载,注册表无需新增层级。宿主组装保留必须共享的部分:注册表本身、跨会话设施、沙箱与审批栈、模型路由。ctx.agentPresets 负责发现与把关,拒绝未激活的行和把服务发布进根 realm 的行。详见 按会话组装 agent presetpreset/

新行为的归属位置

新行为附加到已有文档记录的扩展点;循环发生变更时,本架构图随之更新。

目标 机制
添加模型提供方 ctx.llm 上注册其适配器
添加面向模型的功能 ctx.tools 上注册schema 加入提示词组装
让某个会话拥有不同的能力集合 在 agent preset 中组装它;其中的 service 行需要 isolate realm
添加 shell 执行 实现并注册 ctx.bash 后端;本地后端通过 ctx.subprocess 生成进程
添加持久化终端执行 注册 ctx.pty 后端和 dsh-tool-pty
添加用户命令 ctx.commands 上注册;适配器无需模型轮次即可发现并分派
添加后台工作 ctx.tasks 上注册;通用 task_* 工具负责收集或停止
添加文件系统访问或策略 实现 ctx.fs 提供方,或监听 fs/* 策略事件
限制生成的进程 使用 ctx.sandbox 后端;消费方在生成前包装 argv
拦截请求、工具或轮次 使用相应的 agent/*tools/* 事件;agent/turn-stopping 是停止边界
添加模型可见上下文 调用 agent.inject(),将带来源的上下文排入下一次获准请求
添加 UI 或编辑器集成 驱动 ctx.agents 并从 session/event 渲染
添加持久会话状态 扩展 SessionEventMap;从日志渲染和回放
添加异步会话标题生成 注册唯一的 ctx.sessionTitle 提供方
管理同会话目标 使用 ctx.goals;通过 Agentagent/* 续跑
fork 活跃会话 调用 ctx.sessions.fork(source, boundary?, childSessionId?)
将注册项限定到单个 agent 使用其 agent.ctx(参见 Agent 作用域)

扩展实操手册cookbook提供插件骨架和功能到服务边界的映射;指南涵盖工具LLM 适配器vendored 包