Files
deepseek-harness/docs/architecture.zh.md
_Kerman bd40eec770 Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/core.md
#	docs/core-data-structures/core.zh.md
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/session.i18n.yaml
#	docs/event-producer-consumer.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/README.zh.md
#	packages/core/agent-loop/src/loop.ts
#	packages/core/agent/README.i18n.yaml
#	packages/core/agent/tests/llm-target.spec.ts
#	packages/core/session/tests/request-header.spec.ts
2026-07-27 16:48:38 +08:00

17 KiB
Raw Blame History

DeepSeek Harness 架构

English | 中文

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

概览

每个 harness 都是一个 Cordis 上下文由各包package贡献服务、类型化事件和可释放的注册项。

packages/core/ 汇集默认的 agent智能体流程各项功能仍以插件形式存在。

默认服务

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.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.invariants support/invariants 按包名筛选包自有运行时检查的注册表

事件

事件构成服务的扩展 API完整清单见事件目录生产方与消费方映射

事件域

  • 会话事件是追加到日志并通过 session/event 发出的持久事实。
  • Agent 事件携带活跃 Agent,用于状态、提示词准入、请求塑形、验证和续跑。
  • 功能事件让所属服务边界无需导入循环即可附加策略和适配器。

拦截语义

waterfall瀑布式事件的行为类似环绕中间件监听器调用 next() 即表示委托,直接返回而不调用它则会否决或接管。完整规则见 Cordis waterfall 语义

默认循环生命周期

已交付的循环通过插件服务和事件,处理从提示词到检查点的工作。

会话采用仅追加方式。每个普通轮次领取一项已排队的 send() 输入;注入不领取输入。后续轮次会等待前一个已领取轮次的检查点,但可以与其共用同一个 running 区间(决策)。模型和插件停止轮次时,该轮次结束;一个步骤包含一次模型请求及其工具。在下文时序中,引号标记持久事件。

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

轮次流程

choose declarative identity and fresh/resume path
  -> prepare private session + agent.ctx -> await unpublished setup
  -> enter session + agent -> session/created -> agent/created
  -> enable driving -> agent/session-start(source) -> start driver
forever:
  wait for a queued message
  claimed message -> agent/prompt-submit
    blocked prompt -> park without opening a turn
    allowed prompt:
      emit agent/status(running)
      'turn/start'
      append prompt + additional contexts as separate 'user/message' events
    STEP loop:
      agent/step
      drain injected context and steering (steering bypasses prompt-submit)
      assemble system prompt and tool schemas
      snapshot the derived messages (the reconstruction boundary)
      'step/start'
      agent/request (config only) -> prepare reasoning/default under turn signal -> log request/header -> llm/stream (frozen, registration-bound)
      'assistant/chunk'
      'assistant/message'
      schedule tool calls by ctx.tools.executionMode:
        exclusive -> one-call barrier
        parallel -> rolling pool, <= maxParallelToolCalls in flight; reclassify before start
        each start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
        each model-order result -> ordered tools/post-execute -> 'tool/result'
      drain accepted tool context and steering
      'step/end'
      continue for tools or steering unless a result concluded the turn
      otherwise agent/stopping -> drain -> continue only for steering
    'turn/end' -> agent/idle
  start the next waking queued message, or emit agent/status(idle)

idle inject:
  append 'user/message'
  do not open a turn or run the model

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

工具执行阶段的上下文,包括活跃轮次内的 inject() 和工具执行后的 additionalContexts会在结果记录完毕后落定。Steering 会在同一边界排空并请求再执行一个步骤。空闲状态下的 inject() 会立即追加上下文,且不改变轮次编号;持久化层会尽快排空。

裁剪先于摘要;溢出重试必须取得持久进展。恢复会在失败步骤关闭后、轮次关闭前通过 agent/request-error 运行。负责处理的策略调用 agent.retry() 安排一个重试轮次;取消优先(压缩重试)。

失败边界

适配器故障会先关闭步骤,再由 agent/request-error 接收准确的 Error、标准化的 LlmFailure 和轮次信号。负责处理的监听器调用 agent.retry();循环关闭失败轮次,并从持久历史开启另一个轮次,中间不发出空闲通知。重试耗尽后,失败的 turn/end 即为终态记录。失败分片不会提交消息或工具调用。

其他故障使用 agent/error。取消和资源释放优先于恢复;轮次信号还会在提交任何请求头之前取消异步模型能力准备,尚未分派的工具会得到合成的 tool/call/ABORTED_BEFORE_DISPATCH 对。实际生效的 cancel(cause) 在清空队列和中止前发出原因;观察方不能否决,空闲调用不发事件。用户或父级取消持久记录为 aborted,等待停稳的资源释放记录为 disposed。原因只改变报告方式,不改变延迟完成的结果上下文处理(决策)。

轮次和步骤事件均位于轮次边界内;空闲时注入的 user/message 可以位于两个轮次之间。重新加载会用合成的轮次结束事件闭合中断尾部。关闭后的故障只使用 agent/error。每个轮次有一个 TurnEndReason

Agent 句柄

ctx.agents 拥有活跃 agent并返回 AgentHandle { agent, dispose() }。插件使用完整的 send() 选项,或使用 followup()steer()inject() 预设;cancel()whenIdle() 控制生命周期。一个需等待完成的 disposer 协调拆卸归属。

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 重建每个请求;由该包提供的 dsh-agent-loop/invariant 可通过 ctx.invariants 断言这一点(可重建性)。

持久性由插件负责。后端会尽快排空同步的 session/event 通知。语义检查点策略使用 session/flush 作为观察屏障:分别位于适配器分发前、顶层工具分发前,以及下一次请求之前的 agent/stepSessionPersistence 直接存储 SessionEvent,并将元数据存入 SessionHeaderJSONL 默认采用带校验和的 ZstandardSQLite 则遵循同一契约(决策)。

ctx.sessions.appendOutOfBand() 会把插件所属的纯日志事件加入开放轮次,或创建一个平衡且已刷写的零步骤轮次。session/title 按后写覆盖方式折叠,并携带源 seq 和来源信息;其即时回退标题和唯一可选异步提供方都不会延迟 agent 响应。fork 会继承标题(决策)。

模型内容

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

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

扩展与组合

功能模式

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

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

dsh-workspace-context 在第一次 agent/step 注入基线,并通过 tools/post-execute 追加 ctx.fs 发现的变更;其决策记录了隔离方式。dsh-paths 负责共享路径。

组合包与应用

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

新行为的归属位置

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

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

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

快速参考