接上篇《Agent 开发入门:Function Call 实战》。上篇讲的是"单次调工具",本篇让它循环起来------这就是 Agent 从"工具人"变成"自主执行者"的关键一步。
目录
[一、从 Function Call 到 Agent:只差一个"循环"](#一、从 Function Call 到 Agent:只差一个"循环")
[二、ReAct 四步循环(背下来,面试必考)](#二、ReAct 四步循环(背下来,面试必考))
[三、完整可运行代码(ReAct Agent)](#三、完整可运行代码(ReAct Agent))
[四、工具设计 4 件套(决定 Agent 聪明不聪明)](#四、工具设计 4 件套(决定 Agent 聪明不聪明))
一、从 Function Call 到 Agent:只差一个"循环"
单次调用做不到"查上海→查北京→算差值"这种连续任务,需要循环:
思考(下一步干嘛)→ 行动(调工具)→ 观察(看结果)→ 再思考......直到能回答
这就是 ReAct 范式(Reasoning + Acting)。
一句话:模型当调度器,工具当执行器,循环当流程引擎。
二、ReAct 四步循环(背下来,面试必考)
① 思考 Thought:模型决定"下一步该干嘛/该调哪个工具"
② 行动 Action:真正去调那个工具
③ 观察 Observation:拿到工具返回的结果
④ 再思考:拿着结果判断"够了没?不够再循环"
后端类比:while循环+状态机------模型是决策者,每轮根据状态决定下一步。
终止条件:① 模型判断够了直接回答 ② 达到max_iterations上限
三、完整可运行代码(ReAct Agent)
工具1:天气
def get_weather(city: str) -> str:
data = {"上海": 28, "北京": 22, "广州": 31}
if city not in data:
raise ValueError(f"没有 {city} 的天气数据")
return f"{city}当前气温 {data[city]} 摄氏度"
工具2:计算
def calc(expr: str) -> str:
try:
return f"计算结果:{eval(expr, {'__builtins__': {}})}"
except Exception as e:
return f"计算出错:{e}"
Agent 循环(ReAct)
def run_agent(user_msg: str, max_iter: int = 5):
messages = [{"role": "user", "content": user_msg}]
for i in range(max_iter):
resp = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=TOOLS)
msg = resp.choices[0].message
if not msg.tool_calls: # 模型觉得够了→直接回答
print("[思考] 无需再调工具,直接回答")
return msg.content
messages.append(msg)
for tc in msg.tool_calls:
name, args = tc.function.name, json.loads(tc.function.arguments)
print(f"[思考] 调工具 {name}({args})")
try:
result = FUNC_MAP[name](**args) # 行动
except Exception as e:
result = f"工具执行失败:{e}"
print(f"[观察] {result}")
messages.append({"role": "tool", "tool_call_id": tc.id, "content": str(result)})
return "(已达最大轮数,仍未能确定答案)"
运行输出(能看到循环):
思考 调工具 get_weather({'city': '上海'})
观察 上海当前气温 28 摄氏度
思考 调工具 get_weather({'city': '北京'})
观察 北京当前气温 22 摄氏度
思考 调工具 calc({'expr': '28-22'})
观察 计算结果:6
思考 无需再调工具,直接回答
上海28度,北京22度,差6度。

注意:模型自动连续调了3次工具(上海→北京→算差)------这就是"自主"。
四、工具设计 4 件套(决定 Agent 聪明不聪明)
name:工具名
description:给模型看的说明书(靠它决定用不用)
parameters:参数schema
func:真干活的代码
最常被忽略的坑:模型只看description,写含糊就乱选工具。
五、工程化必备:4个防崩措施
异常捕获(try/except)
max_iterations(防死循环)
结果清洗(别喂垃圾)
结构化错误(让模型兜底)
六、过关清单
☐ Agent能自主完成"多工具串联"任务
☐ 能讲清"思考-行动-观察"循环(ReAct)
☐ 改description能观察模型选工具行为变化
☐ 工具出错时Agent能捕获不崩溃
☐ 设了max_iterations防死循环
七、常见坑(5个)
-
description写太泛→乱选工具(写清何时用/输入输出)
-
schema类型不对→填参报错(严格type+required)
-
工具没异常捕获→一个挂全崩(try/except)
-
无限循环→烧token(max_iterations)
-
原生错误喂回模型→被带偏(先清洗)
八、面试必答
Q:Agent怎么防止死循环?
A:① max_iterations轮数上限 ② 工具返回结构化错误让模型纠偏 ③ 异常捕获+超时。核心是"循环必须有终止条件"。
下一篇预告:《Agent 开发:多 Agent 协作实战------LangGraph 编排从策划到执行》。欢迎关注专栏「后端转AI实战指南」,持续更新。
📌 配套代码:(Star支持)
【官方权威来源】
- ReAct论文 --- Yao et al. (2022), ICLR 2023, arXiv:2210.03629(ReAct范式原始出处)
https://arxiv.org/abs/2210.03629
- OpenAI Function Calling 官方文档(工具JSON Schema/tool_calls)
https://platform.openai.com/docs/guides/function-calling
- OpenAI Agents 官方指南(Agent循环/终止条件)
https://platform.openai.com/docs/guides/agents
- LangChain Agents 官方文档(Agent抽象/ReAct执行器)
https://python.langchain.com/docs/concepts/agents/
【内部整理来源】
-
《后端转AI应用工程师·实战电子书》第5天上午「单Agent工具调用」章节(ReAct原理/工具4件套/代码)
-
《求职最短路径·半天计划》Day 5(过关清单与验收标准)
-
《Agent开发》(第二周-Agent模式/第三周-ReAct反思)
版权说明:本文为原创技术分享,代码示例基于 OpenAI 官方 API 用法编写,可自由学习使用。