AI 智能体的执行原理
很久没更新。这篇把「AI 智能体到底是怎么把一件事做完的」按执行过程写清楚。不讲某一家产品的界面,只讲运行时里反复发生的那几步。
先把对象说清楚
普通对话模型做的是一次生成:你给一段上下文,它回一段文字,然后停住。
智能体多出来的是一个会停下来再出发的循环。它面对的不是「回答这句话」,而是「把这个目标做完」。做完往往要经过好几轮:想下一步、调用一个工具、看工具返回了什么、再决定要不要继续。
所以智能体不是另一个更长的提示词。它是模型,加上一套负责循环、调用工具、记下观察的运行时。
一次执行里有四样东西
跑起来之前,运行时手里通常有这些:
- 目标。用户这句话,以及系统提示里规定的完成标准。
- 模型。负责决定下一步。它不直接碰文件、网络或数据库。
- 工具。搜索、读文件、跑命令、发请求。每件工具有名字、参数和返回值。
- 记忆。眼下这场对话的上下文,以及写在外面的笔记、文件或检索结果。
模型负责「下一步做什么」。运行时负责「真的去做,并把结果送回来」。两边分开,后面很多现象就好理解了。
主循环
把一次任务收成这个循环:
- 组装上下文。把目标、可用工具、已经发生的步骤,整理成模型这次能看见的输入。
- 让模型决定。模型要么给出最终答复,要么给出一次或多次工具调用。
- 执行工具。运行时检查参数、真正调用,拿到一份观察。
- 把观察写回去。观察成为下一轮上下文的一部分。
- 检查是否停止。完成、失败、步数或预算到顶、或者碰到需要人确认的动作,就退出。否则回到第 1 步。
用一段接近运行时的伪代码看:
state = { goal, tools, history: [] }
while not stopped(state):
decision = model.next(state)
if decision is final_answer:
return decision.text
for call in decision.tool_calls:
observation = tools.run(call.name, call.arguments)
state.history.append(call, observation)
return stopped_reason
model.next 每次只产生一个决定。tools.run 才接触外部世界。历史被追加,而不是被模型自己记在权重里。这场任务的过程,活在 state 里。
用一个小任务走一遍
目标:查明天上海会不会下雨。会下雨的话,写一条短提醒;不会就说明天不用带伞。
第 1 轮。 上下文里只有目标和两个工具:weather.lookup(city, date)、notes.write(text)。模型还没有观察,它不应该编一个降雨概率。合理的决定是调用天气工具,参数是上海和明天的日期。
第 2 轮。 运行时执行查询,观察写回,例如:「明天有雨,降水概率 80%。」模型看见的是这条观察,不是它自己的猜测。这时它决定调用 notes.write,写入一句提醒。
第 3 轮。 笔记工具返回「已写入」。目标里的两件事都有了对应观察:查过天气,也写下了提醒。模型给出最终答复,循环结束。
注意顺序。模型不能在第 1 轮就声称「已经查过了」。查过这件事,只存在于工具返回之后。
工具调用实际长什么样
模型输出的不是一段自然语言里的「请帮我搜一下」,而是运行时能解析的结构,大致是工具名加上参数:
{
"name": "weather.lookup",
"arguments": { "city": "上海", "date": "2026-10-10" }
}
运行时接着做三件事:
- 这个名字在不在允许的工具列表里。
- 参数是否符合约定,比如日期是不是缺了。
- 调用是否越过权限。读公开天气和删除文件不是同一级动作。
然后才执行。返回值再被包成观察,例如「调用成功」或「参数错误:缺少 date」。失败也是观察。下一轮模型应当根据失败改参数或换一条路,而不是假装成功。
规划是怎么出现的
循环本身不规定模型要不要先写计划。常见有三种安排,差别在于提示和运行时约束,不是三套互斥的引擎。
边想边做。 每一步先写一句当前判断,再调用一个工具,看到结果再想下一步。适合目标清楚、但路径要看现场的任务,比如查资料、改一处报错。这种交错常被叫做 ReAct:推理和行动挨在一起。
先计划再执行。 模型先列出步骤,运行时按步骤推进,每步仍然可以调用工具。适合边界清楚的流程,比如「备份、修改配置、再检查服务是否起来」。计划写错了就要允许改计划,否则会按一份过时的清单走到底。
做完再看。 一轮行动之后,另一次模型调用专门对照目标:做成了没有,哪一条观察对不上。对不上就回到循环里补。这能拦住「工具其实失败了,却写出一份顺利的总结」。
三种可以叠在同一次任务里。先有个短计划,执行时边想边做,结束前再对一下目标。
记忆放在哪里
模型单次能看见的长度有限。执行一长,早期的工具输出会把后面的目标挤出去。所以记忆要分开看:
- 工作记忆就是当前这次调用带上的上下文:目标、最近几步、还没消化的观察。
- 外部记忆是运行时另外保存的东西:一份任务笔记、检索到的文档片段、代码仓库里的文件。需要时再取回工作记忆。
实用的做法是把已经确定的结论写短,把原始的大段输出留在外面,下一轮只带回结论和出处。这样循环还能继续,而不是在半路把上下文塞满。
什么时候该停
停止条件要在循环外面写死,不能只指望模型自己说「我好了」:
- 模型给出最终答复,并且关键步骤都有观察支撑。
- 步数、时间或费用到达上限。
- 同一个工具带着同一组参数重复失败。
- 下一个动作不可逆,或者会影响别人,需要人点头再继续。
上限尤其重要。没有上限的循环,会在一个错误观察上一直重试。
它为什么会跑偏
执行原理也解释常见的失败,而不只解释顺利的情况。
把猜测写成观察。 模型在工具返回之前就声称查到了结果。运行时如果把这种话当成事实收进历史,后面每一步都站在假观察上。
重复同一步。 观察里没有新信息,模型却再次发出同一个调用。运行时应当识别重复,并把「这次没有新结果」写进下一轮,或者直接停止。
计划和现场不一致。 计划写的是三条命令,环境里第二条已经不存在。不会改计划的执行,会在第二条上耗完步数。
上下文被早期错误污染。 一次错误的文件内容进了历史,后面的修改都基于它。外部记忆如果也不更新,错误会被一遍遍取回来。
这些都不是模型突然不聪明了。是循环把某一步的输出当成了下一步的输入,错误因此留下来。
人和运行时各自守哪一段
使用智能体时,人要给出的是目标和约束:做成什么样、哪些工具可以用、哪些动作必须先问。运行时要守住的是循环本身:解析工具调用、执行、记录观察、执行停止条件。
模型每一轮只回答「基于我现在看见的这些,下一步是什么」。它看不见自己没被送进上下文的文件,也看不见没有执行过的工具。
把这三句话记住,再去看任何一个具体产品,界面不同,执行原理都还是这条循环。