从零搭建可运行Agent系统:主循环调度、工具注册与上下文管理实战
简介这份资源是面向具备一定Python基础的开发者与AI应用学习者的Agent系统搭建指南配套源码包聚焦从零构建可自主搜索、生成报告并自动归档笔记的智能体系统帮助读者理解Researcher、Editor、Note Taker三角色分工与工具调用机制。压缩包共9个文件约15KB以4个py脚本承载核心逻辑辅以txt依赖清单、md说明文档、example环境变量示例及gitignore等配置项结构精简便于直接运行与二次修改。目前已有150人学习下载。读者可据此获得一套可运行的Agent最小实现涵盖搜索工具与笔记工具的接入方式、角色协作流程以及RAG与Agent结合的应用思路适合作为入门实践与项目原型参考。1. 从零搭一套能跑的 Agent 系统这份可运行源码到底解决了什么很多人第一次接触 Agent 系统卡住的地方不是概念而是「跑不起来」。你翻了一堆讲 ReAct、Tool Calling、Memory 的文章脑子里大概知道 Agent 就是「大模型 工具 循环」但真到自己动手光是环境依赖、工具注册、循环终止条件这几块就能耗掉一整天。这份《搭建Agent系统指南》配了可运行源码定位很明确它不是又一篇讲原理的科普而是一套能让你在本地把 Agent 主循环跑通、再按自己需求替换工具和模型的代码骨架。适合两类人——刚转过来做 AI 应用、想先跑通再理解的开发者以及已经用过现成框架、但想搞清楚底层调度逻辑的熟手。软件开发里最怕的就是「黑匣子」这套源码的价值就在于把调度、工具调用、上下文管理这几层摊开给你看。2. Agent 主循环拆解调度、工具注册与上下文管理Agent 系统和普通「一问一答」的调用最大的区别在于它有一个循环。普通调用是「输入 → 模型 → 输出」Agent 是「输入 → 模型判断要不要调工具 → 调工具 → 把结果塞回上下文 → 再问模型 → 直到模型认为可以给最终答案」。这个循环看着简单但每一环都有工程上的取舍。下面按源码里最常见的三层结构拆开讲。2.1 调度层谁来决定下一步做什么调度层是整个 Agent 的大脑它负责把用户输入、历史消息、可用工具列表打包成一次模型调用然后解析模型的返回判断是「直接回答」还是「请求调用工具」。常见做法是用一个 while 循环加最大轮次限制避免模型陷入死循环。# 调度主循环控制 Agent 的最大推理轮次 MAX_TURNS 8 # 防止无限循环一般 5~10 足够 def run_agent(user_input, tools, model_client): messages [{role: user, content: user_input}] for turn in range(MAX_TURNS): # 把工具描述一并传给模型让它自己决定是否调用 response model_client.chat(messages, toolstools) if response.tool_calls: # 模型要求调用工具执行后把结果追加进上下文 for call in response.tool_calls: result execute_tool(call.name, call.arguments) messages.append({role: tool, name: call.name, content: result}) else: # 没有工具调用说明模型给出了最终答案 return response.content return 达到最大轮次仍未收敛请检查工具定义或提示词这段代码里MAX_TURNS是最关键的参数。设太小复杂任务跑不完设太大一旦模型逻辑出错就会空转烧 token。我一般从 8 起步观察日志里实际用了几轮再调。execute_tool是工具执行入口它需要根据call.name找到对应函数这里要做一层白名单校验不能直接拿模型给的名字去反射调用否则是个安全隐患。2.2 工具注册把函数变成模型能看懂的描述模型本身不知道你有哪些函数它靠的是你提供的工具描述schema。工具注册的核心就是把一个 Python 函数翻译成「名字 功能说明 参数结构」这三样东西。参数结构一般用 JSON Schema 描述模型据此生成调用参数。# 工具注册用装饰器把普通函数登记为 Agent 可调用工具 TOOL_REGISTRY {} def tool(name, description, parameters): def decorator(func): TOOL_REGISTRY[name] { name: name, description: description, parameters: parameters, # JSON Schema 格式 func: func, } return func return decorator tool( namequery_weather, description查询指定城市的当前天气用于回答天气相关问题, parameters{ type: object, properties: { city: {type: string, description: 城市名称如 北京} }, required: [city], }, ) def query_weather(city): # 实际项目里这里换成真实 API 调用 return f{city} 当前晴气温 22 度description写得越清楚模型选错工具的概率越低。血泪经验是描述里一定要写「什么时候用这个工具」而不只是「这个工具做什么」。比如上面写了「用于回答天气相关问题」模型在遇到天气提问时命中率会明显提高。parameters里的required字段也要老实填否则模型可能漏传参数执行时报 KeyError。2.3 上下文管理消息怎么拼、历史怎么裁Agent 跑多轮之后messages会越来越长迟早撞上模型的上下文窗口上限。上下文管理要解决两件事一是消息顺序不能乱工具调用和工具结果必须成对出现二是超长时怎么裁剪。常见做法是保留 system 提示 最近 N 轮 对早期内容做摘要。策略做法适用场景滑动窗口只保留最近 N 条消息短任务、对话式 Agent摘要压缩把早期消息交给模型总结成一段长任务、需要记忆前文关键信息抽取只保留工具结果里的结构化字段工具返回内容很长的场景裁剪时最容易翻车的是把「工具调用」和「工具结果」拆散了。模型看到一条孤立的 tool 消息会直接报错所以裁剪必须以「轮」为单位不能按单条消息切。我一般会在裁剪函数里加一个断言检查 tool 消息前面是否紧跟对应的调用消息不满足就往前多留一条。3. 从源码到可运行环境、依赖与第一次跑通拿到一份源码包第一件事不是急着改代码而是先原样跑通。跑不通就改等于同时引入两个变量出了问题根本分不清是环境还是代码。这一章按「装依赖 → 配密钥 → 跑 demo → 看日志」的顺序走一遍。3.1 环境准备与依赖安装源码包一般是 Python 项目依赖清单在requirements.txt或pyproject.toml里。建议用虚拟环境隔离避免和系统里的其他包打架。# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖建议加国内镜像加速 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple装完先别急着跑用pip list确认关键包版本。Agent 类项目最常见的版本冲突是模型 SDK 和 HTTP 库不匹配比如某个 SDK 要求 httpx 的特定大版本装错了会在调用时报奇怪的序列化错误。如果requirements.txt里没锁版本建议手动把模型 SDK 固定到一个已知可用的版本。3.2 模型接入配置密钥、地址与超时源码里通常有一个配置文件或环境变量读取入口。模型接入要配三样API Key、接口地址、超时时间。前两个是必须的超时经常被忽略但 Agent 多轮调用下单次超时设太短会导致工具还没返回就被判定失败。# config.py集中管理模型接入参数 import os MODEL_CONFIG { api_key: os.getenv(MODEL_API_KEY, ), base_url: os.getenv(MODEL_BASE_URL, https://api.example.com/v1), model_name: os.getenv(MODEL_NAME, default-model), timeout: 60, # 单次请求超时Agent 场景建议 30~60 秒 max_retries: 2, # 网络抖动时的重试次数 }密钥一定走环境变量不要硬编码进源码再提交。timeout这个参数在 Agent 里比普通调用更重要因为一次用户请求可能触发好几轮模型调用每轮都卡一下整体体验会很差。max_retries设 2 就够设太多遇到持续性错误会拖很久才报错。3.3 跑通第一个 Demo 与日志观察源码包一般会带一个demo.py或examples/目录。先跑最简单的那个观察完整的一次 Agent 循环。# 运行示例观察 Agent 的完整推理过程 python demo.py --query 帮我查一下北京现在的天气然后推荐穿什么跑的时候重点看日志里这几样模型第一次返回是直接回答还是请求调工具、工具参数传得对不对、工具结果有没有正确回填、最终答案有没有用上工具结果。如果模型压根没调工具八成是工具描述写得不够明确或者 system 提示里没告诉它「有工具可用」。如果调了工具但参数错了回去检查 JSON Schema 的description和required。这一步的日志是后面所有调试的基础建议把日志级别调到 DEBUG把每次请求和响应都打出来。4. 避坑与排查Agent 跑不起来时先看这几条Agent 系统的报错往往不直观模型不报错但行为不对比直接抛异常更难查。下面这几条是我在实际项目里反复遇到的按「现象 → 原因 → 解决」整理。现象一模型一直不调用工具直接编答案。原因通常是工具描述太笼统或者 system 提示里没有明确「遇到 X 类问题必须用工具」。解决方法是把工具描述改成「当用户询问……时使用」并在 system 提示里加一句「涉及实时数据的问题必须调用工具不要凭记忆回答」。现象二工具调用报参数缺失或类型错误。原因是 JSON Schema 定义和函数签名对不上比如 schema 里写integer但函数收的是字符串。解决办法是让 schema 和函数签名严格一致并在execute_tool里加一层参数校验类型不对就返回明确的错误信息给模型让它重试。现象三多轮之后报上下文超长。原因是历史消息没裁剪或者工具返回内容太长。解决方法是加滑动窗口或摘要压缩同时对工具返回做截断比如只保留前 2000 字符超出部分用省略标记。现象四循环停不下来一直调同一个工具。原因是模型陷入了「调用 → 结果不满意 → 再调用」的循环。解决办法是设MAX_TURNS硬上限同时在工具结果里加入「如果这个结果已经能回答问题请直接给出最终答案」的提示。现象五本地跑通换台机器就报依赖错误。原因是依赖没锁版本或者用了系统级的隐式依赖。解决办法是生成requirements.txt时带上版本号pip freeze requirements.txt并在 README 里写清 Python 版本要求。提示排查 Agent 问题时先把MAX_TURNS设成 1强制模型只做一次判断这样能快速区分是「调度逻辑错」还是「多轮累积错」。5. 进阶玩法换模型、加工具与效果验证跑通 demo 只是起点真正让这套源码产生价值的是按自己的场景改造。这一章讲三个最常用的进阶操作以及怎么验证改完之后没跑偏。5.1 替换模型与多模型混用源码里的模型接入一般抽象成了一个 client 类换模型只需要改配置或换一个 client 实现。常见做法是把「规划用强模型、执行用便宜模型」拆开主循环里判断意图的那次调用用能力强的模型工具执行后的总结用便宜模型能明显压成本。# 按阶段选择不同模型规划用强模型总结用轻量模型 def chat(messages, toolsNone, stageplan): model MODEL_CONFIG[strong_model] if stage plan else MODEL_CONFIG[light_model] return client.chat(modelmodel, messagesmessages, toolstools)stage参数由调度层传入规划阶段传plan工具结果总结阶段传summarize。这样改的好处是不用动主循环逻辑只在一处控制模型选择。5.2 新增自定义工具的完整流程加工具就三步写函数、加装饰器、确认注册。但有几个细节决定它能不能被正确调用。函数返回值尽量是字符串或可序列化的结构别返回复杂对象参数名和 schema 里的properties键名必须一致如果工具有副作用比如写文件、发请求要在描述里写清楚让模型知道这个操作不可逆。tool( namesave_note, description把用户要求记录的内容保存到本地笔记文件用于备忘场景, parameters{ type: object, properties: { content: {type: string, description: 要保存的文本内容} }, required: [content], }, ) def save_note(content): with open(notes.txt, a, encodingutf-8) as f: f.write(content \n) return 已保存加完之后用一句明确会触发它的 query 测一下比如「帮我记一下明天要开会」看日志里有没有出现save_note的调用记录。5.3 效果验证怎么判断 Agent 改好了还是改坏了Agent 的效果验证不能只看「这次回答对不对」要拆成几个可观测指标。我一般会准备一组固定测试用例每次改完跑一遍对比下面这张表里的指标。指标怎么看合格线参考工具命中率该调工具时有没有调目标场景 90%参数正确率工具参数有没有传错 95%平均轮次完成任务用了几轮越少越好观察趋势最终答案可用率人工判断答案是否解决问题按场景定测试用例要覆盖三类必须调工具的、不需要调工具的、需要连续调多个工具的。每次改提示词或加工具后都跑一遍避免「修好一个、弄坏一个」。从那以后我每次改完 Agent 的提示词或工具定义都强制走一遍这组回归用例哪怕只改了一个字。希望这套源码和上面的拆解能帮你少走点弯路把 Agent 真正跑在自己的场景里。本文还有配套的精品资源点击获取

相关新闻

AI助手跨会话记忆中间层:从无状态到可检索的智能对话记忆方案

AI助手跨会话记忆中间层:从无状态到可检索的智能对话记忆方案

最近折腾了一套代号叫claude-mem的对话记忆中间层,目的是解决一个再常见不过的问题:AI 助手聊完一次就“六亲不认”,第二次见面照样把你当陌生人。这套方案的核心思路不是让模型“记住”,而是让模型“查得到”——把每一次对话沉淀…

2026/10/12 13:46:58 阅读更多 →
claude-mem:给你的AI助手装上跨会话长期记忆

claude-mem:给你的AI助手装上跨会话长期记忆

如果你经常用 AI 助手处理代码、写作或者做调研,一定经历过这种崩溃:昨天明明和它反复敲定了方案细节,今天开个新会话,它一副“你是谁”的表情,上下文全丢了,只能从头开始铺垫。更难受的是,那种…

2026/10/12 13:46:58 阅读更多 →
文本向量化实战:从语义坐标到工业级检索落地

文本向量化实战:从语义坐标到工业级检索落地

1. 项目概述:为什么“文本变坐标”正在成为基础能力你有没有遇到过这样的场景:在一堆会议纪要里找某次关于“交付延期”的讨论,结果关键词搜不到——因为原文写的是“项目节奏调整”“客户侧排期微调”“上线窗口后移”;又或者&am…

2026/10/12 13:46:58 阅读更多 →

最新新闻

WorkBuddy低代码工作流实战:从单点任务到业务闭环

WorkBuddy低代码工作流实战:从单点任务到业务闭环

1. 这不是一场普通征稿:WorkBuddy 应用指南征集背后的“真实战场”你点开这个标题,第一反应可能是——又一个企业发的软广?领积分、换周边?听起来像行政部发的季度团建通知。但如果你真这么想,就错过了一个正在 quietl…

2026/10/12 14:47:16 阅读更多 →
电商平台数据分析系统Python实现:从数据清洗到可视化全流程解析

电商平台数据分析系统Python实现:从数据清洗到可视化全流程解析

简介:这是一套基于Python实现的电商平台数据分析系统课程大作业源码包,面向计算机、自动化及相关专业的学生,适用于期末课程设计、课程大作业、毕业设计等场景。项目围绕电商订单数据展开,涵盖数据读取、数据清洗、数据分析与可视…

2026/10/12 14:47:16 阅读更多 →
深度学习股票预测与量化策略:LSTM+遗传算法实战解析

深度学习股票预测与量化策略:LSTM+遗传算法实战解析

简介:一套完整的深度学习股票预测与量化策略研究项目,面向高校计算机相关专业毕业设计、课程设计与期末大作业场景,也适合正在做项目实战练习的学习者。项目源自大四毕业设计,经导师指导并获99分高分评价,Python源码完…

2026/10/12 14:47:16 阅读更多 →
zoxide智能目录跳转:用frecency算法重塑终端cd体验

zoxide智能目录跳转:用frecency算法重塑终端cd体验

1. 先搞懂zoxide是怎么记住你的目录的 1.1 终端痛点与zoxide解题思路 如果你每天要在终端里来回切换项目目录、配置目录、日志目录,大概率经历过这么几个场景:项目文件夹层层嵌套,明明上周才进去过,今天就忘了完整路径&#xff0…

2026/10/12 14:47:16 阅读更多 →
用户体验五层模型实战:从战略层到表现层的产品设计指南

用户体验五层模型实战:从战略层到表现层的产品设计指南

1. 从“能用”到“爱用”:用户体验为什么成了产品生死线做产品的人大概都经历过这样的场景:功能列表拉出来几十项,技术指标全部达标,测试用例通过率百分之百,上线之后数据却纹丝不动。用户来了,看了一眼&am…

2026/10/12 14:47:15 阅读更多 →
AutoClaw智能体实战:从澳龙订单场景解析任务自动化与跨系统编排

AutoClaw智能体实战:从澳龙订单场景解析任务自动化与跨系统编排

1. 从一条热搜说起:这个项目到底在折腾什么前几天刷到一条挺有意思的消息,标题大意是某科技大厦里“游出”了澳龙,同时一个叫 AutoClaw 的智能体工具宣布上线。乍一看像是美食博主和科技博主串台了,但仔细一琢磨,这背后…

2026/10/12 14:46:14 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →