上一篇讲了 DeepSeek Harness 的“一切皆插件”:模型、工具、Skills、Sandbox,甚至 Agent Loop,都可以在运行中加载、替换和卸载。
但能力能够动态变化,只解决了一半问题。一个新工具加入以后,什么时候可以调用?用户在执行途中补充的要求,什么时候交给模型?工具执行失败后,任务从哪里继续?这些问题最终都要回到 Agent 的运行过程。
很多人第一次写 Agent,都会从一个简单循环开始:把问题交给模型,模型需要工具就执行工具,再把结果交回模型,直到它给出最终答案。
DeepSeek Harness 的源码里也有这个循环。只是当 Agent 真正开始工作,循环周围很快会出现更多问题。
Agent 正在修改代码,用户突然补充一句“不要动测试文件”,这句话应该什么时候生效?模型一次要求读取五个文件,是并行还是串行?某个工具准备删除文件,谁来确认?用户中途取消任务,已经启动的工具怎么办?对话越来越长,又该保留什么、丢掉什么?
这篇沿着一条消息的执行过程,看看 DeepSeek Harness 如何用 Inbox、Turn、Step、Session 和工具管线,把一个简单循环变成可以长期运行的 Agent。

消息不会直接交给模型
在 DeepSeek Harness 中,用户消息会先进入 Agent 的 Inbox,也就是收件箱。
收件箱会区分几种情况。普通问题留给下一个任务;用户在运行中的补充,放到最近的下一步;后台产生的上下文可以先存着,等 Agent 本来就要继续时再带给模型,不必单独唤醒它。
比如 Agent 正在排查测试失败,用户补充“先不要修改代码”。正在执行的日志查询可以继续,但下一次请求模型时,这条限制必须出现。它既不是一个新任务,也不应该强行闯入已经发出的模型请求。
这个小小的收件箱,解决了 Agent 运行中最常见的问题:新消息什么时候生效。
一个任务里,模型可能被调用很多次
DeepSeek Harness 把一次用户任务称为 Turn,把任务内部的一次模型请求称为 Step。
用户说“找出测试失败的原因”,这是一个 Turn。Agent 可能先运行测试,再读取报错文件,然后查看最近修改,最后给出结论。整个过程只有一个 Turn,却包含多个 Step。
这样划分以后,系统才能知道当前任务有没有结束、工具执行后要不要继续、用户的新消息属于当前任务还是下一个任务。模型请求失败时,也能判断应该重试当前步骤,还是结束整个任务。

Session 记录的是运行过程
普通聊天程序通常保存“用户说了什么、助手回答了什么”。DeepSeek Harness 记录得更细:任务何时开始、模型何时返回、调用了什么工具、工具结果对应哪次调用、每一步怎样结束。
下一次请求模型时,Harness 再从这些记录中生成它需要看到的消息。
这和分布式系统里的事件日志很像。日志保存发生过的事实,对话界面、模型上下文、调试时间线和恢复状态,都是从这些事实生成的不同视图。
这样做还有一个好处。上下文太长时,Harness 可以压缩模型看到的旧历史,同时保留原始运行记录。压缩发生在下一次模型请求之前,也可能在模型明确报出上下文溢出之后。它管理的是整个 Session 的模型视图,并不只在 Turn 结束时处理。
模型提出行动,Harness 决定能不能执行
模型返回“删除这个文件”,并不等于文件马上被删除。工具调用还要经过策略检查、用户审批、权限判断、沙箱执行和结果处理,最后才写回 Session。
模型负责决定下一步想做什么,Harness 负责把这个决定变成一次受控行动。
如果模型一次调用多个只读工具,Harness 可以让它们并行执行。但工具完成得再快,结果仍按照模型发起调用的顺序写回。执行可以并行,模型看到的历史不能随着线程调度随机变化。

放到 Claude Code 和 Pi 旁边,就更容易看懂
Claude Code、Pi 和 DeepSeek Harness 都有 Agent Loop,也都要处理工具调用、会话记录和上下文过长的问题。区别不在于谁有循环,而在于它们把哪些部分交给开发者。
Claude Code 首先是一款完整的编程 Agent。用户面对的是已经组装好的产品:它接收任务、读取代码、调用工具,并在上下文变长时自动整理历史。消息如何调度、工具如何排队、会话如何恢复,这些运行细节通常不需要用户关心。
Pi 更像一个小而透明的 Agent 内核。它保留了完整的运行能力,但代码结构更容易理解和修改。Pi 用 JSONL 记录会话,并通过树形结构支持分叉和返回历史节点。开发者可以在它现有的循环上增加工具、扩展和上下文处理逻辑。
DeepSeek Harness 关注的是另一组问题。它把 Inbox、Turn、Step、Session、工具执行和上下文处理拆成明确的运行边界,并让这些部分也能通过插件组合。开发者不仅可以增加一个工具,还可以替换模型、存储、Sandbox,甚至 Agent Loop。
可以简单理解为:
Claude Code:一套已经组装完成的 Agent 产品Pi:一个容易阅读和修改的轻量 Agent 内核DeepSeek Harness:一套支持动态组合的 Agent 运行机制
这三者不完全处在同一个层次,也不适合简单比较谁更强。如果目标是直接完成编程任务,Claude Code 提供了更完整的使用体验;如果想用较少代码理解或改造一个 Agent,Pi 更直接;如果想研究 Agent 的能力如何在运行中被加载、替换和撤销,DeepSeek Harness 暴露了更多运行边界。
DeepSeek Harness 并没有发明一种不同的 Agent Loop。它把原本堆在循环周围的职责拆开,让消息调度、工具治理、状态记录和插件生命周期可以分别改变。
while 循环之外是什么
沿着 DeepSeek Harness 的源码走一遍,会发现主循环并不复杂:接收输入,调用模型,执行工具,记录结果,判断是否继续。
复杂的是循环周围的规则。消息什么时候生效,任务从哪里开始、在哪里结束,危险操作怎样阻止,并发结果怎样保持稳定,用户怎样中途介入,上下文超长后怎样继续,这些问题共同决定了 Agent 能不能长期可靠地工作。
Agent 在代码形式上当然可以是一个 while 循环。但从工程上看,真正决定它能不能长期工作的,是循环周围的消息调度、任务边界、状态记录、工具治理和上下文管理。
上一篇讲“一切皆插件”,回答的是 Agent 如何在运行中改变能力。这条运行主链路回答的是另一件事:当能力、消息和任务都在动态变化时,系统如何保持可控。
DeepSeek Harness 把这些问题拆成了可以记录、拦截和替换的边界。插件让 Agent 能够变化,运行主链路让这种变化不至于失控。
本文由作者@YannTalk,授权发布于平台,未经许可禁止转载。

