第5讲 · Agent Loop——一轮对话的完整生命周期

《DeepSeek Harness 从上手到精通》系列 · 第二阶 核心概念篇

🎯 目标:看懂 turn/step 主循环,理解"模型-工具-模型"如何转起来 难度 ★★☆ ⏱ 约 25 分钟 前置:第 4 讲 插件框架基础

本讲要回答一个看似简单的问题:用户发一句话,到收到回答,中间到底发生了什么?答案藏在 packages/core/agent-loop 的源码里。本讲需要一点 TS 阅读耐心,但全程不写代码。


一、turn 与 step:两层循环

dsh 的主循环有两层,先用一个比喻分清:

  • turn(轮):用户发一条消息,到 agent 给出最终回复,算一个 turn。一个会话由许多 turn 串起来;
  • step(步):一个 turn 内部,模型可能多次"思考→调用工具→看结果",每一次模型推理 + 一次工具执行,就是一个 step。

一句话:一个 turn = 若干 step 的循环,循环在"模型不再要求调用工具、直接产出最终文本"时结束。

Agent Loop 的 turn/step 循环
图 1 一个 turn 由多个 step 组成:模型推理 ⇄ 工具执行,直到模型给出终答。

二、工具执行流水线:查找 → 把关 → 执行 → 回填

当模型在某一步决定调用一个工具,工具不会"直接跑"。它要走完一条流水线:

工具执行流水线
图 2 工具执行四阶段:注册表查找 → 把关(guard/approval)→ 执行 → 结果回填。
阶段发生了什么
注册表查找ctx.tools 里按名字找到工具定义
把关 guard/approval守卫规则先过滤,敏感操作触发审批(第 2 讲见过)
执行真正调用工具函数,拿到原始结果
结果回填把结果写回事件流,作为下一步模型的输入

为什么有"把关"这步? 它把安全策略插在"模型想做"和"真的去做"之间——这正是 dsh 敢让模型自动跑命令的底气。

三、系统提示词与工具 schema 的动态组装

很多人以为系统提示词是写死的。在 dsh 里,system-prompt 包会动态组装:基础人设 + 当前可用的工具 schema(由 ctx.tools 当前挂载情况决定)+ 配置片段。这意味着:

  • 你挂载/卸载一个工具,模型"看得见的能力"会立刻变化;
  • 改系统提示词片段,不用重编译,热更新即可(呼应第 4 讲 effect)。

四、对照官方 architecture.md 轮次流程图

官方 architecture.md 有一张轮次流程图。读它时,把上面三节套进去:外层是 turn 循环,内层每个 step 是"推理→工具流水线→回填",系统提示词在每轮开始时重新组装。带着这个骨架去读源码,会比逐行啃轻松很多。

五、动手练习:讲清"一句话到回答"的 6 件事

本讲产出是文字作业。对照流程图,把"用户发一句话 → 收到回答"拆成至少 6 个环节,例如:

1) 用户消息进入 turn 2) 组装系统提示词 + 工具 schema 3) 模型推理,决定调用某工具 4) 走工具流水线(查找/把关/执行/回填) 5) 结果回填为下一步输入,模型再推理 6) 模型不再调用工具,产出终答,turn 结束

把这份清单存成笔记,第 6 讲讲"事件日志"时,你会看到这 6 步每一步都对应一类事件。

六、常见坑

  • 分不清 turn 和 step:记住——turn 是"一问一答",step 是"答的过程中模型的一次思考+动作";
  • 以为工具是模型直接执行的:中间隔着注册表查找和把关,报错先查这两步;
  • 改提示词不生效:确认改的是被动态组装的那一段,而不是缓存里的旧版本;
  • 源码版本漂移agent-loop 路径在 preview 期可能调整,认准 packages/core/agent-loop 入口。

七、官方文档对应章节

  • docs/architecture.md 轮次流程图
  • 源码 packages/core/agent-loop
  • packages/system-prompt 动态组装逻辑

本讲内容基于 DeepSeek Harness 官方文档与项目源码整理,仅供学习参考,具体命令与配置请以官方最新版本为准。系列文章配合源码仓库食用效果更佳:https://github.com/deepseek-ai/deepseek-harness

咨询 DeepSeek Harness 相关问题,请加微信:A0qingfengyuan_01

个人观点,仅供参考,如有不对之处,请多包涵,欢迎指出。本文由 AI 协助完成!