很多 Agent 系统的问题,表面上看是模型不够稳定,实际上是我们一开始就把问题放错了位置
Agent 出错以后,我们很容易先去改 prompt
它没有遵守规则,就把规则写得更细。它没有理解背景,就塞更多上下文。它不会操作,就继续接工具。它执行流程混乱,就再加一层编排
这些改动看起来都合理,而且短期内通常也会有一点效果。但真正用久了会发现,很多问题并没有被解决,只是换了一种方式重新出现
规则写进去了,长任务后半段还是会失效。工具接上去了,Agent 还是不知道什么时候该用。计划拆好了,执行过程中还是会跳步、合并步骤,最后给出一个“看起来完成”的结果。上下文补得越来越多,系统反而越来越重,越来越难判断问题到底出在哪里
其实,问题不一定是模型没听懂,也不一定是信息给得不够,而是我们一直在用“对话模型”的方式设计 Agent
但 Agent 和普通 LLM 最大的区别,不是它更会推理,而是它会行动
它会读文件、写文件、调用工具、修改状态、触发流程。只要它开始行动,它就不再只是生成一段文本,而是在改变一个外部环境
所以 Agent 工程真正要回答的问题,不只是怎么让模型给出更好的回答,而是怎么给这个会行动的模型,设计一个可运行、可观察、可约束、可恢复的环境
“模型包含智能,而 Harness 是让智能变得有用的系统”
错觉:问题出在 prompt 和 context
当 Agent 表现不稳定时,最自然的做法就是补 prompt
它漏掉某条规则,就把规则写进 system prompt。它不知道项目背景,就塞更多文档。它忘了之前的决策,就把历史记录再总结一遍。它工具用错了,就在提示词里加一段“工具使用注意事项”
这些做法当然有用。Prompt 和 context 是 Agent 工作的基础。Prompt 让模型理解目标,context 让模型获得信息。没有清晰指令和足够上下文,Agent 只能在信息真空里猜
但问题在于,它们主要作用在模型的一次推理输入上
也就是说,它们解决的是:模型这一次该听到什么、该知道什么、该倾向于怎么行动
它们不直接解决另一类问题:工具调用前是否需要权限判断,文件被修改后有没有记录,外部副作用是否可追踪,任务中断后能不能恢复,Agent 声称完成后是不是真的完成,人接手时能不能复盘整个过程
这些问题不是“说清楚一点”就能解决的
“prompt 约束是说服,不是强制。模型「理解」了规则不等于「遵守」了规则——你无法用更多的字来对抗概率性的遗忘”
因为当 Agent 从回答问题变成执行任务以后,真正失控的地方经常发生在模型行动之后。它不是没听懂,而是听懂以后做了一件系统没有承接好的事
这也是为什么很多时候继续加 prompt 会让系统变得更重,而不是更稳
更长的 prompt 可能让模型更容易遵守规则,也可能让重点被稀释。更多的 context 可能给模型更多信息,也可能让它在无关材料里迷路。规则写得越细,越容易变成一份只在开头出现、在长任务后半段被注意力衰减冲掉的说明书
所以,Agent 不是缺一句更完美的提示词,而是缺一个能承载行动后果的环境
Agent 的关键变化:从输出文本到改变状态
普通 LLM 的输出主要是文本
它可以总结、解释、改写、生成方案。即使答错了,大多数时候错误也停留在文本层。用户可以不采纳,可以追问,可以重新生成
Agent 不一样
Agent 会把模型的判断接到工具上。它可以读文件、写文件、执行命令、调用 API、创建任务、发送消息。模型不再只是生成下一句话,而是在选择下一步动作
这带来一个根本变化:Agent 的错误不只会出现在回答里,还会出现在世界状态里
一次错误的总结可以删掉;一次错误的工具调用可能已经修改了文件、污染了数据、触发了通知、消耗了资源,或者把流程推进到了错误阶段
所以 Agent 系统不能只问“模型输出是否合理”,还要问一组更工程化的问题:它行动前看到的状态是什么?它为什么选择这个动作?这个动作改了哪些东西?有没有越过权限边界?结果有没有被验证?如果失败,系统停在了什么状态?后续的人或 Agent 能不能接着处理
这些问题的答案,不应该只存在于模型上下文里
上下文会被压缩,会过期,会丢失,也会随着新一轮会话消失。让一个会改变外部状态的 Agent 只依赖临时上下文,就像让一个工程团队只靠口头记忆管理项目
真正需要被设计的,是 Agent 行动所在的环境
这个环境要承载状态,限制权限,记录事件,暴露工具,返回反馈,并在必要时允许人接管。只有这样,Agent 的行动才不会只是一次模型输出的延伸,而会变成系统中可观察、可恢复、可治理的一部分
为什么长任务里,规则会慢慢失效
很多人第一次遇到 Agent 不听规则时,都会觉得很困惑
规则明明写了,为什么它后面还是忘?流程明明说了,为什么它执行一半还是跳步?Skill 明明注入了,为什么它一开始遵守,越到后面越像没看见
我觉得这里很容易误判成“模型不够聪明”或者“prompt 不够严格”
但很多时候,问题不是规则没有写进去,而是规则在长上下文里失去了注意力优势
“LLM 是一个基于上下文进行概率性推理的系统,具有三个并列的本质特征:输出由上下文决定,输出是概率性的,工作记忆是有限且易失的”
模型对上下文不是平均阅读的。通常来说,开头的系统提示和离当前输出最近的内容,更容易被模型注意到。中间的大段信息,尤其是在上下文越来越长之后,很容易被后续内容淹没
所以你在第一步注入的规则,到第一百步的时候并没有真正消失。它还在上下文里,但已经不再是模型最优先注意的内容
这能解释很多长任务里的常见现象
比如 Agent 到后期开始“赶工”,把本来应该一步步完成的任务合并处理。它不一定是在故意偷懒,而可能是在上下文接近上限时,自然倾向于压缩输出、减少细节
再比如规则开始失效。不是它完全不知道规则,而是最近几十轮工具结果、修改记录、反馈意见占据了更强的位置,早期规则被挤到了注意力边缘
这时候,单纯把规则写得更长,未必有用
“Context Engineering 的指导原则是:寻找能够最大化产生期望结果可能性的最小、高信号 Token 集”
真正有效的往往是“重申”:在任务推进过程中,持续把当前最重要的信息重新放到模型最容易注意的位置
这也是任务清单、进度记录、阶段性总结真正有价值的地方。它们不只是记录进度,更重要的是不断提醒模型:现在做到哪一步,下一步要做什么,当前阶段应该遵守哪些关键约束
但这也引出另一个问题:如果所有重要信息都要靠上下文里反复重申,那系统会越来越臃肿。什么该常驻,什么该按需加载,什么该在最新位置重复,什么又应该交给外部系统机械检查,就变成了 Agent 工程里非常关键的设计取舍
缺的不是更好的 Agent,而是 Environment
早期做 Agent 架构时,很容易把 Environment 当成 Agent 的附属物
Agent 需要读文件,就给它文件工具。需要执行命令,就给它 shell。需要查系统,就接一个 API 或 MCP server。需要记忆,就在上下文里塞历史摘要。需要验证,就让它自己检查一遍
这种做法在 Demo 阶段很自然,因为任务短、状态少、参与者也只有一个 Agent
但一旦任务变长,或者出现多人、多 Agent、跨 session 协作,这个边界就会变得模糊
状态到底属于谁?历史操作保存在哪里?另一个 Agent 接手时看到什么?人类介入时看到的是聊天记录,还是系统真实状态?权限是工具自己判断,还是由统一边界判断?一次工具调用产生的外部影响,后面还能不能追踪和补偿
这些问题如果都让 Agent 自己在上下文里处理,系统会越来越脆弱
更清晰的拆法是:Agent 和 Environment 不应该是包含关系,而应该是协作关系
- Agent 是 actor,负责理解目标、制定计划、选择动作、调用工具、根据反馈调整下一步
- Environment 负责保存状态、管理权限、记录事件、暴露接口、执行或转发副作用,并把观察结果返回给 Agent
也就是说,Agent 不应该拥有世界状态。Environment 才应该承载世界状态
这看起来只是架构边界调整,但影响很大
如果状态属于 Agent,那么 Agent 退出,状态就容易丢;换一个 Agent,历史就要重新解释;多人协作时,每个参与者都可能看到不同版本的世界
如果状态属于 Environment,那么 Agent、人类、CLI、MCP client、后台任务都只是作用在同一个环境上的不同 actor。它们可以通过不同接口进入,但共享同一份状态、权限和事件记录
这也是一次性 Agent Demo 和更可靠 Agent 系统之间的分界线之一:Demo 里,Environment 是 Agent 的工具箱;生产里,Agent 应该只是 Environment 中的一个行动者
一个可运行环境,到底要补什么
说 Environment 可能还是有点抽象。落到工程里,它其实就是一组很具体的问题
第一是状态
Agent 行动前,必须有一个明确的状态基准。当前任务推进到哪一步,哪些事情已经完成,哪些判断已经做过,哪些结果可以复用,哪些地方不能重复改,这些信息不能只存在于聊天上下文里
如果没有外部状态,Agent 每次换 session 都像一个刚入职的新同事,需要你重新解释整个世界
第二是权限
Agent 能调用工具,不代表它应该随便调用工具
读文件、写文件、执行命令、访问网络、调用外部 API、修改真实数据,是完全不同的风险等级。权限不应该只是“弹窗确认”,而应该是环境能力边界。哪些动作默认允许,哪些动作需要人工确认,哪些动作永远禁止,哪些动作只能在沙箱里发生,这些都应该被系统表达出来
第三是工具接口
工具不是越多越好,而是越清晰越好
Agent 需要的是职责明确、输出稳定、错误可理解的接口。CLI、API、MCP、workflow 都可以成为工具接口,但关键不是协议本身,而是工具是否把真实系统能力以 Agent 可判断的方式暴露出来
一个工具如果太碎,Agent 就要在大量细节里拼装流程;一个工具如果太宽,一次错误调用就可能产生不可控影响。好的工具接口应该把能力和边界一起交给 Agent
第四是事件日志
只保存最终状态是不够的
Agent 系统还需要知道每一步是谁做的、基于什么状态、调用了什么工具、返回了什么结果、产生了什么副作用。否则一旦结果异常,就只能在聊天记录里考古
Event Log 的价值不只是审计,也是恢复、调试和学习。它让系统可以回答:Agent 为什么走到这一步,哪个操作导致状态变化,哪个外部调用已经发生,哪一步可以重试,哪一步需要补偿
第五是反馈
Agent 最大的问题之一,是很容易“看起来完成”
它能写出完整总结,也能自信地说任务已完成。但生产系统不能依赖自信,必须依赖反馈
“将评估者与生成者分离。自我评分是失败模式”
反馈可以来自测试、lint、规则检查、运行指标、评估器、人工 review,也可以来自真实环境中的观察结果。关键是把“我认为完成”改成“系统证明完成”
第六是恢复
只要 Agent 会行动,就一定有可能会失败
所以环境必须设计恢复路径:checkpoint、rollback、resume、handoff、retry、compensation。否则失败之后只能重新开一轮对话,让模型凭残缺上下文猜之前发生了什么
生产级 Agent 不要求永远不失败,但要求失败后状态清楚、边界可控、下一步可继续
第七是影响范围
Agent 越有用,能触达的系统越多,风险也越大
真正可靠的边界不能只靠 prompt 或模型分类器,因为它们都是概率性的。沙箱、文件系统边界、网络出口控制、凭证隔离、只读/读写权限,才是限制影响范围的硬边界
“概率性防御只能改变倾向,确定性边界才限制能力”
这不是为了束缚 Agent,而是为了让它能在边界内更自由地行动。边界清楚了,系统才敢把更多任务交给它
再看 Harness
如果一开始就讲 Harness,很容易把它理解成某个新框架、新架构,或者更高级的 prompt 技巧
但当我们先经历完前面这些问题,再回头看 Harness,就会发现它其实没有那么神秘
它描述的不是某一个组件,而是一整套组织方式:怎么把 prompt、context、tools、state、permission、feedback、recovery 这些东西组织起来,让 Agent 能在真实环境里行动
“Harness 本质是控制论的双环控制:前馈预先注入约束,反馈在行动前后自动拦截与纠偏”
Prompt 负责表达意图。Context 负责提供信息。Tools 负责连接外部能力。Environment 负责承载状态和副作用。Feedback 负责判断结果是否成立。Harness 则负责把它们组合成一个 Agent 能稳定行动的结构
所以 Harness 的目标不是把 Agent 管死
如果只追求控制,最安全的做法就是不给 Agent 工具、不让它写文件、不让它访问外部系统。但那样得到的不是可靠 Agent,而是一个被限制到没有行动能力的聊天机器人
好的 Harness 应该做的是:让 Agent 看到足够但不过载的信息,调用清晰且受控的工具,在明确边界内自由选择路径,行动后立刻得到反馈,并让系统记录过程,方便人类观察、接管和恢复
这里的核心取舍是:在确定性边界内,释放模型的不确定性能力
模型的不确定性并不全是缺点。它能探索不同路径,补全缺失信息,处理模糊需求,在运行中根据观察调整策略。Agent 的价值正来自这种灵活性
但灵活性必须被放在一个可承受的环境里
边界、权限、日志、验证、恢复,不是为了替模型思考,而是为了让模型的行动后果可见、可控、可修正。Harness 做得越好,Agent 反而越不需要被人逐步指挥。因为系统已经替它准备好了能行动、能反馈、能纠错的环境
8. 结尾:环境决定 Agent 上限
Agent 的能力不只来自模型,也来自它所处的环境
Prompt 决定模型如何理解任务。Context 决定模型知道什么。Tools 决定模型能触达什么。但 Environment 决定模型能否把理解转化为可靠行动
这也是为什么很多 Agent Demo 很容易做出来,而生产级 Agent 很难落地。Demo 可以忽略状态、权限、日志、反馈和恢复,只要这一次看起来完成就够了。生产系统则必须面对行动后果:改了什么、影响了谁、是否可验证、失败后如何继续、人能不能接管
所以,Agent 工程的重点不是停留在“怎样写出更好的 prompt”,而是我们能不能为 Agent 设计一个足够清晰的环境?
在这个环境里信息是可获得的,工具是可理解的,权限是有边界的,过程是可追踪的,结果是可验证的,失败是可恢复的,人也始终可以介入
“Human steer, agents execute”
只有进入这样的环境,模型的智能才不只是一次漂亮的回答,而会变成一种可以持续使用的系统能力