今天读到一篇讲 Agent 演进的文章,觉得讲的挺好的,做个笔记。

现在大家聊 Agent,动不动就谈自主规划或者多智能体。最原始的大模型其实只有一个能力,给一段输入,算出一串最可能的下一个词。

下面以牛马张三为例,讲一下智能体(Agent)是怎么从模型一步步走向生成环境的。

单次调用与黑盒

早上九点,张三坐到工位上,打开网页,熟练地在对话框里敲下一行字,“今天珠海天气怎么样?”

模型把这句话读进去,按概率吐出一段回答。这时候既没有上下文概念,也没有外部工具,它就是一个纯粹的文本映射函数。

张三很快发现了问题。他明天再来问,还得把地点完整敲一遍。如果他偷懒只发一句“今天天气怎么样”,模型根本不知道他在哪里。

问答与上下文装配

为了让张三少敲几个字,工程师在模型前面加了一层处理。

系统把张三的工位常驻地“珠海”、当前系统时间,连同张三随手敲下的“今天天气怎么样”拼接在一起,可能还附上一句系统提示“请用简洁口吻回答”。模型拿到的不再是张三发的那句话,而是系统组装好的长文本。

这看起来只是简单的字符串拼接,却定下了后来几乎所有智能体框架(Harness)的底色。模型眼前看到的世界,完全是由宿主系统替它搭出来的。

历史挑哪几轮放进去、哪些规则权重更高、长了以后该裁剪哪一段,全由外部逻辑说了算。模型只对眼前拼好的这一屏文本负责。

上午十点多,张三在群里就撞上了这个问题。业务方反馈团队做的知识库助手答非所问,连小说角色的年龄都推不出来。张三调出日志排查,发现用户前面跟 AI 聊了一长串角色的生平经历,最后随口问了一句“这个人现在多少岁”。系统在组装上下文时触发了历史裁剪规则,直接把最早记录出生年份的那几轮对话删掉了。

模型眼前根本没有出生年份的字样,只能老老实实回答没有足够信息。回答质量的好坏,直接被这一层上下文装配卡住了脖子。

ReAct 让推理和动作交替

到了十一点,张三要开始写代码了。他把终端里的报错信息贴进输入框,“本地编译失败,请帮我修复”。

光靠刚才那种拼文本,模型只能根据训练集里的记忆胡猜几句可能的原因,根本看不到张三本地的代码长什么样。

ReAct 架构把推理和外部动作拆成了一轮轮交替的循环。

模型看到报错后,先想一步,“我得先看一下报错文件对应的代码行”。系统收到这个意图,替它去本地磁盘读取那几行代码,拿到结果并塞回上下文。模型看了眼代码,再想第二步,“这里少了一个分号,我需要改写这个文件”。

这一步,模型才算从自说自话的文本生成,变成了能根据外部观察结果不断修正下一步动作的循环。

有了这个循环,Agent 算是有了一点干活的样子,只不过眼下它还只能按规矩做些简单动作。

工具调用规范化

下午两点,张三想让模型直接帮他把改好的文件提交到 Git 仓库。

这时候自由格式的文本就靠不住了。模型如果随手在回答里写一句“请帮我执行 git commit”,宿主程序很难准确知道它到底想跑什么命令、参数是什么,一不小心还可能把格式解析错。

系统必须给模型划定严格的动作规范。

  • 工具定义(Tool Schema),向模型明确声明有哪些工具、名字叫什么、需要传哪些参数。例如声明一个名为 run_git_command 的工具,参数是合法的命令字符串。
  • 工具路由(Tool Router),模型根据规范吐出结构化的调用参数,系统拦截下来,找到对应的底层执行逻辑,做完参数校验再替它执行。
  • 工具结果(Tool Result),命令跑完以后,无论成功还是报错,系统都带上这次调用的唯一标识打包成固定格式,放回上下文让模型继续判断。

从这一刻起,模型的输出不再是一段给人读的文字,而是变成了驱动系统运行的结构化指令。

记忆系统与长期状态

下午四点,张三在这个工程里已经连续聊了几十轮。对话越来越长,模型的上下文窗口快要放不下了,而且单次调用的费用也越来越高。

系统不能把这几十轮历史原样带下去,必须把记忆拆成不同层次。

一部分是当前轮次随身带的短期工作记忆(Working Memory),比如眼下正在讨论的这个函数。另一部分则是存在外面的长期记忆(Long-term Memory),等需要的时候再去检索。

在张三的工作环境里,这些记忆通常分属不同类别。

  • 程序记忆(Procedural),写在项目根目录的规则文件或者 Skill 里,规定好这个仓库用什么代码风格、跑测试用什么命令。
  • 语义记忆(Semantic),团队积累的项目术语、架构规范和业务常识,平时躺在向量库或者索引文件里,张三问到相关模块才捞出一两条。
  • 情景记忆(Episodic),半小时前某次编译失败的原因、张三刚才否决掉的改法,记录在近期的日志轨迹里,避免同一处坑再踩一遍。

怎么存相对简单,难在什么时候写、什么时候捞。什么信息值得记下来?重复的记录怎么合并?捞多少条才不挤占当前写代码的窗口?这些策略的复杂度,超过了调模型本身。

Harness

傍晚六点,张三准备下班。临走前他在界面上点下确认,让系统在后台继续跑完剩下的一整套测试与部署。

这时候保障整个流程运转的,已经不仅仅是中间那个模型了,而是一整套被称为 Agent Harness 的运行时系统。模型负责想下一步该干什么,Harness 负责管这一步在什么上下文、权限、生命周期和持久化规则下跑起来。

面对张三在一天里的各种诉求,业界对 Harness 的设计权衡也大不相同。

  • 如果张三只是在本地写个小脚本,Pi Agent 这类极简 Harness 就够用了,核心逻辑只管调用和返回,不设防复杂的权限拦截,胜在轻巧快当。
  • 如果张三在团队的大工程里协作,需要会话随时可中断、进度随时可恢复、操作轨迹随时可审计,系统就得像 OpenCode 那样用重度事件驱动把状态管严。
  • 如果张三放权让助手大面积修改文件、执行系统脚本,系统就必须像 Codex Harness 那样卡死安全沙箱,涉及关键变更时必须弹窗等张三确认。
  • 如果张三希望共事一段时间后,这个助手越来越懂自己的编码习惯与暗号,系统就得像 Hermes Agent 那样在外部长出一层持续演进的认知状态。

张三这一天的经历,从早上一句简单的查天气,到下班前复杂的自动化流程,模型底层的计算并没有发生根本变化。

工程师在模型四周一层层垒起来的工程系统,才让模型能够稳定跑在生产环境里。


参考文献

从一次 LLM 调用到完整 Harness,Agent 到底经历了什么?