- 它在跑一个循环。每转一圈,把系统提示词、到目前为止的对话、工具清单打包,发给模型。
- 模型的回复里要用工具,就执行,把结果接到对话后面,再转一圈;不要工具了,循环结束。
- 模型自己不记事。每转一圈,前面的内容都要整份重发(对话太长时会先压缩,第 04 章讲)。
Agent 程序的核心是一个循环:问模型;模型要用工具,就执行,把结果接上再问。后面每一章,都是在这个循环身上做文章。
DSH 是什么?DSH(DeepSeek Harness)是 DeepSeek 开源的 Agent 程序,和 Claude Code、Codex 是同一类东西:你交代一件事,它让模型去想、让工具去做,直到办完。这本书把它拆开,看它是怎么搭起来的。
例子:你说“数数这个目录里有几个 .py 文件”。模型看不到你的目录,于是回复:请用 bash 执行 ls *.py | wc -l。Agent 照办,拿到结果 7。
接下来再问模型时,模型是怎么知道结果是 7 的?
点一个选项。
回到开头的问题:Agent 程序到底在跑什么?第一步,先看它的核心:Agent 循环。
while (true) {
const 回复 = await ctx.llm.stream({
system: 系统提示词,
messages: 会话里记下的所有消息,
tools: 工具清单,
})
记进会话(回复)
const 工具调用 = 回复里的 tool-call
if (工具调用.length === 0) break // 不要工具了,结束
for (const 调用 of 工具调用) 记进会话(await 执行(调用))
}
这是简化过的 DSH 真实代码(中文是为了好读)。真实代码多了中途取消、出错重试这些分支,骨架就是这几行。四个角色都在里面:
ctx.llm.stream(…)发请求、收回复。整份请求每圈都重新拼system最初排在最前,模型靠它知道自己是谁、该怎么干活(之后变了,有的模型会在后面收到新版本,第 06 章)tools 和 执行(调用)先告诉模型有哪些工具;模型点名要用,再去执行while (true)把这三样串起来,直到模型不再要工具两个词后面会一直用(DSH 官方用词):从你发来一句话,到循环 break、回复你,叫一个轮次;循环转一圈,也就是问一次模型、再执行它要的工具,叫一个步骤。一个轮次通常包含好几个步骤。
第二步:看这个循环一圈一圈怎么转。重点看右边:第二次发给模型的请求,前面的内容全部重发了一遍。
第三步:回头看循环代码里的 ctx.llm。连模型、管工具、拼系统提示词,都不是循环自己写的。
在 DSH 里,这几样各是一个单独的部件,叫插件:
ctx.llm 用它循环只认 ctx 上的名字,不管背后是谁在干活。所以换个模型、加个工具,都不用动循环的代码。插件是怎么接上去的,下一章讲。
循环什么时候停?
模型一次要了两个工具。下一步发给模型的请求里有什么?
数 .py 文件这件事,一共用了几个轮次、几个步骤?
这一章只讲了主线。想看 DSH 自己怎么描述这个循环: