01Bread Agent · 第 3 章
总进度 3 / 33让 Agent 连续调用工具
ch01 我们让 AI 调了 一次 工具。但真实任务往往要 多步配合 :
2026-09-28约 45 分钟140 行代码难度 ★★★
如果想获取全套课程资料,请关注微信公众号 「AI面包君」,回复 「课程资料」 即可领取。
1. 一个任务可能需要几次工具调用
ch01 我们让 AI 调了一次工具。但真实任务往往要多步配合:
用户:把 README.md 第一行内容写到 hello.txt
AI 内部要做的事情:
- 调
read_file("README.md")拿到全文- 切出第一行(这一步 LLM 自己脑子里就能做)
- 调
write_file("hello.txt", first_line)- 用中文告诉用户"完成了"
这个任务要先读文件,再写文件,最后回复用户。ch01 在一次工具执行后就结束,处理不了这种需要接着行动的过程。
这就是为什么我们需要一个循环——反复地:"调模型 → 拿到工具请求 → 执行工具 → 把结果写回 messages → 再调模型 ...",直到模型不再要求调工具为止。
下面先用一小段代码表示这个循环,后面再看完整实现:
for step in range(MAX_STEPS):
response = client.chat.completions.create(messages=messages, tools=TOOLS_SCHEMA)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
return msg.content # ← 出口:模型不要求调工具了,任务结束
for call in msg.tool_calls:
result = TOOLS_IMPL[call.function.name](**json.loads(call.function.arguments))
messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
读这段时,可以拿刚才的文件任务逐步对应:读文件的结果在哪一轮加入 messages?写文件发生在哪一轮?什么时候停止?理解这些位置,比背下代码更有用。
<!-- bread-visual:start -->
<!-- bread-visual:end -->图解: 工具执行结果进入 messages,成为下一次决策的依据。 循环还需要 MAX_STEPS 兜底;工具报错也可以作为结果回填。
2. 跑起来
cd ch02_loop
python main.py
此时main函数中输入的需求是:读取origin.txt文件的前3行,并把第1行内容写入到一个到文件new.txt中
Anaconda 同学:
D:\anaconda3\envs\yutong\python.exe main.py

预期输出
[step 0] 调用 read_file({'path': 'origin.txt'})
[step 0] 结果: 你好,我是这个文件的第一行
你好,我是这个文件的第二行
你好,我是这个文件的第三行
[step 1] 调用 write_file({'path': 'new.txt', 'content': '你好,我是这个文件的第一行\n'})
[step 1] 结果: 已写入 new.txt (14 chars)
[最终回答] 已完成:origin.txt 的前3行分别是「你好,我是这个文件的第一行」「你好,我是这个文件的第二行」「你好,我是这个文件的第三行」,其中第1行已写入 new.txt。

试读到这里 · 后续内容已封存
关注公众号,继续把这章学完
在「AI面包君」发送关键词「学习AI」拿到口令。验证一次,这个浏览器就能继续阅读全部课程。