如何让程序像人一样,把大任务拆成小步骤,调用外部工具获取信息,并记住已经做过的事情,最终给出可靠的答案?
一个“最小可用”的 Agent 并不需要庞大的模型或复杂的多智能体框架,只需四个彼此协作的组件:
规划器(Planner)、工具执行器(Tools)、记忆机制(Memory)和主循环控制(Main Loop)。
一、规划器(Planner)—— 决策的“大脑”
规划器负责回答一个核心问题:“根据当前已知信息,下一步该做什么?”
它有两种实现模式,可以根据场景切换:
🅰 状态机模式(轻量、确定、无需 LLM)
将任务分解为多个阶段,每个阶段检查记忆中的特定标志,然后决定调用哪个工具。
例如,对于一个“先计算后搜索”的任务,状态机逻辑为:
# 检查记忆中的工具返回记录has_calc=any('计算结果'instr(msg)formsginmemoryifmsg['role']=='tool')has_search=any('AI Agent'instr(msg)formsginmemoryifmsg['role']=='tool')ifnothas_calc:# 阶段1:执行计算return{'tool_calls':[{'function':{'name':'calculator','arguments':{'expression':'12*9+34-10'}}}]}elifnothas_search:# 阶段2:执行搜索return{'tool_calls':[{'function':{'name':'search_info','arguments':{'query':'AI Agent 发展现状与未来趋势'}}}]}else:# 阶段3:所有工具已完成,生成最终回答return{'content':'综合所有结果……','tool_calls':[]}这种模式无需调用大模型,速度快、成本低,适用于流程固定的任务。
🅱 LLM 模式(灵活、泛化、带工具描述)
当任务千变万化时,我们让大模型本身充当规划器。只需在系统提示中附上可用工具的schema(函数名、参数、用途),并让模型输出结构化的tool_calls或最终回答。示例提示片段:
系统:你是一个能调用工具的助手。可用工具:
calculator(expression):计算数学表达式search_info(query):搜索当前信息
根据用户问题,决定调用工具或直接回答,并以 JSON 格式返回。
LLM 会根据当前记忆(对话历史)自主决定调用哪个工具、调用几次,甚至进行反思修正。
两者对比(✅ 表示优势,⚖️ 表示权衡)
| 特性 | 状态机模式 | LLM 模式 |
|---|---|---|
| 决策依据 | 硬编码规则 | 模型推理 |
| 执行速度 | ✅ 极快 | 较慢(需 API 调用) |
| 成本 | ✅ 几乎为零 | 每次规划需付费 |
| 任务灵活性 | 低(需预定义流程) | ✅ 高,适应新任务 |
| 可解释性 | ✅ 决策路径清晰 | 依赖模型解释 |
| 对记忆的依赖 | 仅检查特定字段 | ✅ 全面理解上下文 |
实际生产环境中,两者常结合使用:用状态机处理标准流程,用 LLM 处理异常或复杂分支。
二、工具执行器(Tools)—— 行动的“手脚”
规划器决定调用哪个工具后,必须有一个机制将工具名称映射到实际函数,并执行它。最直接的方式是维护一个字典(注册表):
TOOL_MAP={'calculator':lambdaexpression:eval(expression),# 生产环境请用安全计算库'search_info':lambdaquery:f"根据搜索结果:{query}—— 这里是模拟返回内容"}# 在循环中执行forcallindecision['tool_calls']:func_name=call['function']['name']args=call['function']['arguments']result=TOOL_MAP[func_name](**args)# 将结果写入记忆(见第三部分)工具可以是任何外部能力:计算器、搜索引擎、数据库查询、API 调用、代码解释器等。关键在于统一输入输出格式,让规划器和记忆机制无感知地处理结果。
三、记忆机制(Memory)—— 经验的“便签本”
记忆是 Agent 的“工作区”,它按时间顺序存储所有消息,包括:
- 系统指令(system):定义角色和行为准则(如“你是一个专业 AI 智能体……”)。
- 用户问题(user):原始任务。
- 工具返回(tool):每次工具执行的结果,通常包含工具名称和返回值。
- 最终回答(assistant):规划器生成的输出。
在 Python 中,记忆就是一个列表:
memory=[{'role':'system','content':'你是一个专业AI智能体,具备任务拆解、工具调用、反思修正能力。'},{'role':'user','content':'计算 12*9+34-10,并介绍当前AI Agent的发展现状与未来趋势'}]# 每次工具执行后追加memory.append({'role':'tool','content':f'计算结果:{result}'})# 最终回答追加memory.append({'role':'assistant','content':final_answer})记忆的作用:
- 为规划器提供“已做之事”的上下文,避免重复操作。
- 在 LLM 模式下,将完整记忆作为对话历史传入模型,让模型理解全局。
- 最终可将记忆持久化,实现多轮对话或断点续接。
四、主循环控制(Main Loop)—— 过程的“发动机”
所有组件需要在一个循环中协同工作,直到任务完成或超出步数限制。循环执行“规划 → 行动 → 观察”三步,形成经典的ReAct(Reason + Act)模式:
max_steps=8forstepinrange(max_steps):# 1. 规划decision=planner.plan(memory)# 状态机或 LLM# 2. 如果有最终回答,结束循环ifdecision.get('content'):final_answer=decision['content']memory.append({'role':'assistant','content':final_answer})break# 3. 否则执行工具调用(行动)forcallindecision.get('tool_calls',[]):func_name=call['function']['name']args=call['function']['arguments']result=TOOL_MAP[func_name](**args)# 4. 观察:将结果写回记忆memory.append({'role':'tool','content':result})# 如果达到最大步数仍未完成,可强制输出当前记忆或报错最大步数(如 8 步)是防止死循环的安全阀。当 Agent 误入重复调用时,能主动退出并提示用户。
五、交互流程
而主循环的每一步都遵循“规划→行动→观察”的闭环:
六、一个完整示例:计算 + 搜索
以用户任务“计算 12*9+34-10,并介绍当前 AI Agent 的发展现状与未来趋势”为例,我们采用状态机模式,步数上限为 8,实际执行轨迹如下:
| 步骤 | 阶段 | 决策依据 | 行动/观察 |
|---|---|---|---|
| 1 | 规划 | 记忆中没有工具返回 | 调用calculator,参数12*9+34-10 |
| 1 | 行动+观察 | 执行计算器,得到 132 | 将“计算结果:132”写入记忆 |
| 2 | 规划 | 记忆中有计算但无搜索 | 调用search_info,参数“AI Agent 发展…” |
| 2 | 行动+观察 | 执行搜索,返回一段描述 | 将搜索返回内容写入记忆 |
| 3 | 规划 | 计算和搜索都已存在 | 生成综合回答,包含数字结果和趋势概述 |
| 3 | 完成 | 输出最终回答,退出循环 | 记忆追加 assistant 内容 |
最终回答(模拟):
计算结果:132
根据搜索:AI Agent 正在从单一智能体向多智能体协作演进,趋势是轻量化、可信化、行业化……
综合以上:本次计算结果为 132;AI Agent 正从单智能体向多智能体协作演进,趋势是轻量化、可信化、行业化。
记忆最终状态(共 5 条消息):
system:你是一个专业AI智能体……user:计算 12*9+34-10,并介绍……tool(calculator):计算结果:132tool(search_info):根据搜索结果:……assistant:综合回答……
七、总结与扩展
一个最小可用的 Agent 架构,其精髓在于“以记忆为纽带,以规划为引擎,以工具为手脚,以循环为节拍”。这种设计具备三个显著优点:
- 可观测性:每一步的决策、行动、观察都被记录,便于调试和审计。
- 可扩展性:新增工具只需注册到
TOOL_MAP,调整规划器逻辑即可。 - 成本可控:状态机模式几乎不消耗模型调用,LLM 模式仅在需要时启用。
可以在最小架构之上叠加更多能力:
- 反思机制:让规划器回顾历史步骤,判断是否需要重新规划。
- 多智能体协作:规划器将任务分配给不同角色的子 Agent。
- 流式输出:在生成最终回答时逐字返回,提升用户体验。