Python Agent 踩坑实录:第一次写 Agent,我忘了加一行代码,循环跑了 200 次
Python Agent 踩坑实录第一次写 Agent我忘了加一行代码循环跑了 200 次摘要本文从一次初学者写 Agent 忘了加最大步数限制、循环跑了 200 次才停的经历出发分析 Agent 循环失控的三个常见原因没有max_steps、工具描述模糊导致模型反复试错、不检查模型是否已经给出答案。文章给出一段 30 行的完整可运行代码和三个必须加的保护措施适合刚接触 Agent 的 Python 学习者。文章目录Python Agent 踩坑实录第一次写 Agent我忘了加一行代码循环跑了 200 次一、问题背景我的 Agent 跑了 200 次才停二、最小复现代码五步循环失控三、原因分析三个初学者常犯的错误错误一用 while True 而不是固定次数循环错误二工具描述写得太模糊错误三没有把模型的最终回答和工具调用区分清楚四、修复方案三个必须加的保护保护一固定循环次数保护二把工具描述写清楚保护三打印每一步看清楚在发生什么完整代码五、初学者容易忽略的其他细节细节一tool_call_id 必须对应细节二messages 的顺序不能乱细节三参数 JSON 解析可能失败六、排查技巧怎么知道 Agent 哪里出了问题方法一打印每一步的消息列表方法二设置一个很小的 max_steps方法三统计工具调用次数七、总结一、问题背景我的 Agent 跑了 200 次才停刚学 Agent 的时候我跟着教程写了一个能查天气的小助手。代码很简单调用大模型如果大模型要调工具就执行工具把工具结果返回给大模型。跑起来后我输入“北京天气怎么样”然后就去倒水了。回来一看终端还在刷屏调用工具: get_weather({city: 北京}) 工具结果: 晴25°C 调用工具: get_weather({city: 北京}) 工具结果: 晴25°C 调用工具: get_weather({city: 北京}) 工具结果: 晴25°C ...重复 200 次Agent 一直在调用同一个工具传同一个参数拿同一个结果永远不结束。我以为是模型的问题换了几个模型都一样。后来才发现问题出在我自己的代码里——我忘了一行最重要的代码。这就是本文要讲的坑——Agent 的循环必须有人为设的上限不能指望模型自己停下来。二、最小复现代码五步循环失控先看错误版本importjsonfromopenaiimportOpenAI clientOpenAI()defget_weather(city:str)-str:data{北京:晴25°C,上海:多云28°C}returndata.get(city,f查不到{city})tools[{type:function,function:{name:get_weather,description:查天气,# 描述太模糊parameters:{type:object,properties:{city:{type:string}},required:[city],},},}]defrun_agent(user_input:str):messages[{role:user,content:user_input}]whileTrue:# 问题在这里没有循环上限responseclient.chat.completions.create(modelgpt-4o-mini,messagesmessages,toolstools,)messageresponse.choices[0].messageifnotmessage.tool_calls:returnmessage.content messages.append(message)fortcinmessage.tool_calls:argsjson.loads(tc.function.arguments)resultget_weather(args[city])messages.append({role:tool,tool_call_id:tc.id,content:result,})print(run_agent(北京天气怎么样))输出调用工具: get_weather({city: 北京}) 工具结果: 晴25°C 调用工具: get_weather({city: 北京}) 工具结果: 晴25°C ...无限循环直到你按 CtrlC问题就在这一行whileTrue:# 没有退出条件三、原因分析三个初学者常犯的错误错误一用 while True 而不是固定次数循环whileTrue:# 危险依赖模型自己停下来初学者容易觉得“模型应该知道自己什么时候完成”。实际上模型可能觉得“信息还不够”继续调用工具模型可能重复调用同一个工具模型可能陷入某种推理循环。永远不要用while True写 Agent 循环。错误二工具描述写得太模糊description:查天气,# 太模糊模型不知道需要传什么参数参数是什么格式参数是必填还是选填模糊的描述会让模型反复试错比如先试{city: 北京}再试{location: 北京}再试{address: 北京}——每次试错都是一次循环。错误三没有把模型的最终回答和工具调用区分清楚ifnotmessage.tool_calls:returnmessage.content看起来没问题但如果模型返回的content是空字符串比如它只是想调用工具这个判断会误判。四、修复方案三个必须加的保护保护一固定循环次数defrun_agent(user_input:str,max_steps:int5):# 加默认参数messages[{role:user,content:user_input}]forstepinrange(max_steps):# 固定次数循环responseclient.chat.completions.create(modelgpt-4o-mini,messagesmessages,toolstools,)messageresponse.choices[0].messageifnotmessage.tool_calls:returnmessage.content messages.append(message)fortcinmessage.tool_calls:argsjson.loads(tc.function.arguments)resultget_weather(args[city])messages.append({role:tool,tool_call_id:tc.id,content:result,})returnf超过最大步数{max_steps}任务未完成# 超限返回提示关键点for step in range(max_steps)保证最多循环 5 次到点自动退出。保护二把工具描述写清楚tools[{type:function,function:{name:get_weather,description:查询指定城市的天气。输入城市名称返回该城市的天气信息。,parameters:{type:object,properties:{city:{type:string,description:城市名称例如北京、上海、深圳,}},required:[city],},},}]关键点描述要包含三要素——做什么、传什么、格式是什么。保护三打印每一步看清楚在发生什么forstepinrange(max_steps):print(f\n[第{step1}步])# ... 调用大模型 ...ifnotmessage.tool_calls:print(f[完成]{message.content})returnmessage.contentfortcinmessage.tool_calls:print(f[工具]{tc.function.name}({tc.function.arguments}))# ... 执行工具 ...print(f[结果]{result})关键点初学者一定要能看到每一步发生了什么才能发现问题。完整代码importjsonfromopenaiimportOpenAI clientOpenAI()defget_weather(city:str)-str:data{北京:晴25°C,上海:多云28°C}returndata.get(city,f查不到{city})tools[{type:function,function:{name:get_weather,description:查询指定城市的天气。输入城市名称返回该城市的天气信息。,parameters:{type:object,properties:{city:{type:string,description:城市名称例如北京、上海、深圳,}},required:[city],},},}]defrun_agent(user_input:str,max_steps:int5):messages[{role:user,content:user_input}]forstepinrange(max_steps):print(f\n[第{step1}步])responseclient.chat.completions.create(modelgpt-4o-mini,messagesmessages,toolstools,)messageresponse.choices[0].messageifnotmessage.tool_calls:print(f[完成]{message.content})returnmessage.content messages.append(message)fortcinmessage.tool_calls:argsjson.loads(tc.function.arguments)print(f[工具]{tc.function.name}({args}))resultget_weather(args[city])print(f[结果]{result})messages.append({role:tool,tool_call_id:tc.id,content:result,})print(f[超限] 达到最大步数{max_steps})returnf超过最大步数{max_steps}print(run_agent(北京天气怎么样))输出[第 1 步] [工具] get_weather({city: 北京}) [结果] 晴25°C [第 2 步] [完成] 北京今天晴天气温 25°C。五、初学者容易忽略的其他细节细节一tool_call_id必须对应messages.append({role:tool,tool_call_id:tc.id,# 必须和上面工具的 id 一致content:result,})如果tool_call_id写错了大模型会报错或者不知道这是哪个工具的结果。细节二messages的顺序不能乱正确的顺序是用户消息大模型的响应包含工具调用工具结果。如果顺序乱了大模型会困惑。细节三参数 JSON 解析可能失败argsjson.loads(tc.function.arguments)模型偶尔会返回不合法的 JSON。初学者可以先打印看print(tc.function.arguments)# 看看实际返回什么argsjson.loads(tc.function.arguments)六、排查技巧怎么知道 Agent 哪里出了问题方法一打印每一步的消息列表fori,msginenumerate(messages):print(f[{i}]{msg})看清楚大模型每一轮收到了什么、返回了什么。方法二设置一个很小的 max_steps调试时把max_steps设为 2 或 3快速看到问题不用等 200 次循环。方法三统计工具调用次数fromcollectionsimportCounter tool_counterCounter()# 在工具调用处tool_counter[tc.function.name]1# 循环结束时打印print(f工具调用统计:{dict(tool_counter)})如果某个工具被调用了很多次说明模型在反复试错。七、总结这次踩坑让我记住了一句话Agent 的循环必须有人为设的上限不能指望模型自己停下来。核心要点回顾不要用while True写 Agent 循环用for step in range(max_steps)max_steps设 5-10 就够了超限要返回明确的提示工具描述要写清楚做什么、传什么、格式是什么每一步都打印出来看清楚在发生什么tool_call_id必须和工具调用的 id 对应。给初学者的三句话先把这 30 行代码跑通比看十篇高级文章都有用出问题先打印每一步的消息列表90% 的问题都能看出来不要急着用 LangChain先用最基础的openai库理解原理。参考资料OpenAI Function Calling 官方指南OpenAI Python SDK 快速开始

相关新闻

工业级电源路径保护:TPS259483AYWPR与STM32F405ZG协同设计

工业级电源路径保护:TPS259483AYWPR与STM32F405ZG协同设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 7:25:12 阅读更多 →
微内核工具系统设计与AI辅助故障排查实践

微内核工具系统设计与AI辅助故障排查实践

1. 工具系统的定位与设计取舍1.1 为什么内核需要一套自己的工具系统写内核最痛苦的一件事,不是功能实现不出来,而是功能写好了之后不知道它到底跑得对不对。前几篇我们把DSH的调度器、内存管理、设备框架都搭了起来,内核能开机、能执行任务了…

2026/10/8 7:25:12 阅读更多 →
2026年 Nature 期刊审稿周期:从 119 天到 899 天

2026年 Nature 期刊审稿周期:从 119 天到 899 天

同样在 2026 年 7 月 15 日发表的三篇 Nature 论文,收到稿件至录用分别用了 119、245 和 899 天。论文及其日期记录可在 Nature 官网的文章页查看。把收到、录用和发表三个日期放在一起,能看到不同论文的时间差,也能区分录用前后的两个阶段。…

2026/10/8 7:24:11 阅读更多 →

最新新闻

Flagsmith 自托管环境变量完全参考指南:API 与前端配置速查手册

Flagsmith 自托管环境变量完全参考指南:API 与前端配置速查手册

后端前端 【免费下载链接】flagsmith Flagsmith is an open-source feature flag platform with remote config, experimentation, and self-hosted or cloud deployment options. 项目地址: https://gitcode.com/gh_mirrors/fl/flagsmith 点击查看 免费下载 本指南…

2026/10/8 7:54:22 阅读更多 →
马尾辫物理模拟技术原理与3D角色动画应用

马尾辫物理模拟技术原理与3D角色动画应用

我无法根据当前输入生成符合要求的博文。原因如下:项目标题“ponytail”为英文单词,直译为“马尾辫”,属于常见发型术语,但未提供任何实质性项目背景、技术指向、应用场景或领域归属(如是时尚造型教程?3D建…

2026/10/8 7:54:20 阅读更多 →
Superpowers实战:TypeScript与skill构建实时协作粒子动画

Superpowers实战:TypeScript与skill构建实时协作粒子动画

1. 项目概述1.1 一次偶然发现:Superpowers 到底是个什么?先说结论:Superpowers 是一套开源的、基于 TypeScript 的实时协作创意编程工具箱。它把开发环境、可视化运行沙盒和多人协作机制打包在一起,你打开以后可以直接在里面写代码…

2026/10/8 7:54:19 阅读更多 →
context-mode详解:MCP协议中上下文协商的核心HTTP头

context-mode详解:MCP协议中上下文协商的核心HTTP头

1. “context-mode”不是功能开关,而是MCP协议中上下文协商的运行态标识最近在多个技术社区和开源项目文档里频繁看到“context-mode”这个词,尤其集中在SQLite FTS5全文检索、MCP协议集成、RuoYi-Vue-Pro这类Java后端框架的插件扩展场景中。它既不是某个…

2026/10/8 7:54:18 阅读更多 →
context-mode:用符号链接与原子切换管理多环境上下文的CLI工具

context-mode:用符号链接与原子切换管理多环境上下文的CLI工具

过去大半年我一直在维护三套微服务环境,每天开盘第一件事就是检查当前 shell 里导出的环境变量有没有切对。有一次部署脚本指向了生产环境,差点把测试数据全清了。从那天起我开始认真考虑,一个叫 context-mode 的 CLI 工具到底应该做成什么样…

2026/10/8 7:54:18 阅读更多 →
PP-TTS 语音合成模型下载与部署实践:FastSpeech2 声学模型与 HiFiGAN 声码器的获取、推理与 Benchmark 全指南

PP-TTS 语音合成模型下载与部署实践:FastSpeech2 声学模型与 HiFiGAN 声码器的获取、推理与 Benchmark 全指南

人工智能深度学习计算机视觉NLP语音 【免费下载链接】models Officially maintained, supported by PaddlePaddle, including CV, NLP, Speech, Rec, TS, big models and so on. 项目地址: https://gitcode.com/gh_mirrors/mo/models 点击查看 免费下载 PP-TTS 是飞…

2026/10/8 7:53:17 阅读更多 →

日新闻

抖音用户主页视频数据爬虫详解:点赞、收藏、分享字段抓取与 TaoToken 统一 Key 配置

抖音用户主页视频数据爬虫详解:点赞、收藏、分享字段抓取与 TaoToken 统一 Key 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:03 阅读更多 →
AI 编程 Trae 国内版与国际版一篇讲透:TaoToken 统一 Key 接入实测

AI 编程 Trae 国内版与国际版一篇讲透:TaoToken 统一 Key 接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:06 阅读更多 →
Claude Desktop 配置第三方推理接口教程:用 TaoToken 统一 Key 打通 API 调用

Claude Desktop 配置第三方推理接口教程:用 TaoToken 统一 Key 打通 API 调用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:07 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:13 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →