Agent开发实战:从API调用到智能体工作流搭建

发布时间:2026/10/22 3:01:51
Agent开发实战:从API调用到智能体工作流搭建 从第5天开始Agent学习终于进入深水区。前两天还在熟悉基础模型的调用方式Day05-06直接切换到“怎么让模型自己干活”的核心问题。这两天的学习量很大但收获也最明显我把一套完整的Agent工作流从设计到实现完整走了一遍。这篇文章就对这两天的内容做一个复盘重点讲我踩过的坑和一些可以直接复用的套路。如果你也在自学Agent开发或者打算从API调用转向智能体应用的开发这篇内容应该能帮你少走不少弯路。1. 为什么Day05-06要聚焦这两块内容1.1 从“会聊天”到“会干活”的关键跨越很多人最初接触大模型时觉得AI就是“你说一句它回一句”顶多是个更聪明的搜索引擎。但Agent学习的核心恰恰是要打破这个被动交互的模式。Day05-06的安排是在基础模型调用熟练之后马上切入Agent最本质的东西让模型拥有感知、决策、执行、记忆的闭环。普通对话和真实Agent的最大区别就是有没有“行动”。对话场景里模型只需要输出一段让用户满意的文字Agent场景里模型必须根据用户目标拆解出步骤选择并调用外部工具再根据工具返回的结果调整下一步动作。比如用户说“帮我把今天的会议记录整理成周报”普通对话只能给出一段整理好的文本但Agent会先去找到会议记录文件读取内容按周报格式生成文本然后保存到指定位置甚至把周报发给相关人。这个跨越看起来只是多接了几个接口实际上带来了一系列连锁问题模型怎么知道该调用哪个工具工具参数怎么传给模型工具返回错误时模型如何恢复用户目标太大时怎么拆解成多个步骤这些恰是Day05-06重点解决的。我自己最初的想法是先去做RAG或模型微调觉得那是“大头”。后来发现方向反了。如果没有把Agent的骨架搭起来RAG做出来也只是一个“带检索的聊天框”而不是一个能独立完成任务的智能体。所以Day05-06把重心放在了Agent的运行机制和最小实现上后续再往里面加记忆、加多Agent协作都会顺很多。1.2 学习路线的取舍不贪多先把骨架搭起来这两天学习材料不少很多教程一上来就是各种高级框架、分布式Agent编排、复杂工作流。我一开始也跟着学但很快发现消化不良名词太多概念之间的关系没理清手也动不起来。后来我调整了策略彻底扔掉“框架优先”的思路回到最原始的执行逻辑。先搞清楚一个Agent自己运行起来最少需要哪几部分然后用最朴素的代码一步步拼。事实证明这个决策非常正确。如果类比建房子我前两天学的模型调用是“搞懂了砖头和水泥怎么用”Day05-06就是在打地基和立柱子。地基是Agent的思维循环柱子是感知、行动、记忆几个模块。柱子立不起来后面装修得再好看也会塌。所以这两天的内容我把它总结成两条主线主线一是Agent架构的整体拆解感知层、决策层、执行层、记忆层分别解决什么问题。主线二是最小可运行Agent的实作不依赖任何重型框架用基础模型接口加几个工具函数让一个Agent真的能跑通“理解问题-拆解任务-调用工具-观察结果-继续执行”的完整循环。这两条主线学完后再去看各种开源框架时思路会完全不同。以前看到的是“它提供了什么”后面看到的是“它用哪种方式实现了哪个模块为什么这么设计”。2. 核心架构拆解Agent到底由哪几块组成2.1 感知层怎么让Agent“看懂”请求和上下文感知层是Agent接收外部信息的入口。普通API调用里输入就是一段用户消息Agent场景下输入可能包含多种形式一句自然语言指令、一份上传的文档、一段系统日志、甚至实时轮询到的状态变化。Day05的一个重要练习是让Agent处理“非结构化输入”。例如用户说“帮我看看今天下午有没有空会议室有的话就订一个把邀请发给A同学”。这句话里包含了好几个关键点时间范围是“今天下午”动作是“查询预订发送邀请”对象是“A同学”状态是“如果空闲才订”。如果模型只做一次问答这很轻松但如果Agent要把这个指令拆成多个步骤就必须先从输入中准确提取这些约束。我做了一个简单验证直接让基础模型输出一个JSON结构包含intent、entities、params几个字段并要求模型把用户指令拆成结构化意图。效果不错但有一个关键心得提示词里必须给出明确的格式约束和少量示例。否则模型会自由发挥导致后面的工具调用环节无法稳定对接。感知层还有一个容易忽略的点不是所有输入都需要完整交给模型。比如一个很长的文件直接塞进上下文会导致注意力分散也加剧费用压力。更合理的做法是先对输入做粗加工截断无效内容、提取章节标题、把关键人名/时间/地点单独列出来再把加工后的信息交给Agent决策。这一步有点类似人看邮件先扫一眼主题和正文摘要而不是每一封都逐字读完。2.2 决策层ReAct模式与任务规划决策层是Agent的“大脑”负责根据当前状态决定下一步做什么。Day05学到的核心模式是ReAct——让模型交替进行推理Reasoning和行动Action然后观察行动结果Observation形成循环。我用自己的话解释这个模式普通对话是“想完了直接说”ReAct是“想一步做一步看一步”。比如任务“整理本季度报销数据”Agent先推理“我需要先找到报销文件”于是执行一个搜索文件的操作工具返回三个文件路径后Agent继续推理“这三个文件里哪些是季度的”于是读取文件头部信息看到第二、三个文件符合要求后Agent再决定“读取全部内容并汇总”。每一步的推理都基于上一步的观察行动也因此有依据。在代码实现上ReAct循环的结构大致如下把所有历史消息包括推理、行动、观察拼进上下文送给模型。要求模型输出一个结构化的行动决策包含thought为什么这样做和action要做什么。如果action是调用工具则执行对应工具函数把返回结果作为一条“观察”消息加到上下文回到第1步。如果action是最终回答则结束循环把回答返回给用户。这个循环简单但很容易失控。最大问题是模型可能陷入“一直在推理永远不行动”的状态。这时候系统提示词必须强制约束当存在可执行工具时必须优先选择工具只有确认任务完成才允许输出最终回答。此外一定要设置最大循环次数防止模型在异常情况下无限调用。2.3 执行层工具调用与动作执行执行层是Agent能“动手干活”的关键也是Day06大部分实操时间的去向。所谓工具本质上就是一段函数输入是明确的结构化参数输出是可解析的结果。例如“读取文件”工具入参是文件路径出参是文件内容文本“发送邮件”工具入参是收件人、主题、正文出参是发送状态。让模型学会调用工具重点有三件事第一工具描述要写得清晰。不要用模糊的话比如“读取文件”而要注明参数格式、类型、取值范围。比如路径必须是绝对路径支持 txt/md/docx 格式。模型是靠工具描述来理解“什么时候该用这个工具”的描述不清晰调用率就会下降。第二参数必须严格校验。模型输出的参数经常有幻觉路径不存在、时间格式写错、中文标点混入。执行层必须对每个参数做校验失败时要返回一个清晰的错误信息让模型下次能纠正。常见的做法是在工具函数里用try/except包住把异常文案转换为“工具执行失败原因xxx”的观察消息。第三工具返回结果要结构化。不要返回一整块杂乱文本最好分成status、data、error等字段。这样模型在下一轮决策时能快速看到是否成功、数据是什么、失败原因是什么。结构化的观察结果能大幅减轻模型的理解负担减少重复出错。2.4 记忆层短期上下文与长期记忆记忆是Agent和普通对话程序最不一样的地方。普通程序可以用一个变量保存历史记录但Agent的记忆要服务于“决策”而不是简单回放。短期记忆最直接的做法就是把对话历史放进上下文窗口。但上下文窗口是有限的而且每轮消息都全量塞给模型费用和延迟都会不断增加。我这两天实验下来发现一个比较实用的办法只保留最近3-5轮关键消息超过的部分压缩成一段摘要放在历史开头。这样模型既不失上下文又不会超过窗口限制。长期记忆对应的是需要跨会话保存的信息用户偏好、之前的项目进展、环境配置等。Day06我测试了最朴素的长期记忆方案所有重要信息都写入一个本地JSON文件需要时用关键词或简单规则检索。比如用户之前提到“我习惯周五晚上开会”这条偏好被写入记忆文件下次Agent规划日程时会先检查记忆文件里有没有时间偏好再决定发会议邀请。很多人一上来就准备上向量数据库、做embedding。但我的建议是如果你的数据量没有上千条先用关键词检索和规则匹配完全够用。等跑通了完整流程再判断是否真的需要向量检索。过早引入重型组件反而会把注意力从核心逻辑转移到基建维护上。3. 实操记录用纯手工方式搭一个最小可用Agent3.1 场景选择做一个“会议纪要整理Agent”Day05-06最核心的产出是一个真能跑起来的“会议纪要整理Agent”。场景选得比较小用户传入一段会议原始记录Agent自动完成“提取任务、整理待办、生成摘要”并把结果保存成一个Markdown文件。选择这个场景有三个原因。第一输入输出边界清晰不会陷入“什么叫整理好”这种模糊问题。第二需要用到至少三种工具读取文件、解析文本、写文件能覆盖工具调用的基本形态。第三结果可验证跑完就能打开文件看效果能带来实实在在的正反馈对学习状态很重要。我强烈建议自学的朋友先选一个这类“小而有边界”的场景不要一开始就做“全自动数据分析助手”这种野心太大的东西。Agent能不能跑通关键不在于模型多强而在于任务边界和工具设计是否清晰。3.2 定义工具函数因为我是在本地实验没有引入重型框架工具就是普通的Python函数。在设计上每个工具都遵循“参数简单、返回结构化”的原则。下面是一个简化版的工具注册逻辑def read_file(path: str) - dict: try: with open(path, r, encodingutf-8) as f: return {status: success, data: f.read()} except Exception as e: return {status: error, error: str(e)} def write_file(path: str, content: str) - dict: try: with open(path, w, encodingutf-8) as f: f.write(content) return {status: success, path: path} except Exception as e: return {status: error, error: str(e)}为了让模型能正确选择工具我还维护了一个工具清单包含工具名、功能说明、参数格式、返回格式。这个清单会写入系统提示词中同时也在上下文里给一个调用示例。举个例子{ tool: write_file, params: { path: /tmp/meeting_summary.md, content: 今天讨论了... } }工具函数的代码并不复杂但有一处容易被忽略参数类型必须严格。比如read_file如果接收一个None路径Python会抛TypeError而模型下一轮可能还搞不清原因。所以我统一在每个工具入口做了防御性检查确保返回的是结构化的错误信息而不是让异常直接打断循环。3.3 编写决策主循环主循环是整个Agent的心脏。它做的事情可以概括为把所有的历史消息拼接到上下文询问模型下一步行动然后执行并返回观察结果反复循环。我用的是非常朴素的while循环逻辑如下def run_agent(user_query): msgs [system_prompt, {role: user, content: user_query}] for step in range(max_steps): response model_client.chat(messagesmsgs) action parse_action(response) if action[type] final_answer: return action[answer] result execute_tool(action[tool], action[params]) msgs.append({role: tool, content: json.dumps(result, ensure_asciiFalse)}) return 超过最大步数任务未完成这个循环有几个关键细节。一是我在所有历史消息里同时保留了模型自己的推理、工具调用和观察结果这样模型能“看到”自己刚才做了什么避免反复提出同一个行动。二是parse_action用的是双保险优先按JSON解析如果JSON失败再用正则匹配输出里的action: xxx和params: xxx部分。为什么这么麻烦因为模型有时候会输出额外文字比如“好的我来处理”如果不把这些噪音去掉工具调用就失败了。三是max_steps必须存在。我一开始没设置上限结果碰到一次模型连续调了十几次工具白白消耗了Token和等待时间。后来固定为8步正常任务基本都够用超时了就返回“需要人工介入”的兜底信息。3.4 提示词设计与参数选择这个小Agent的系统提示词我改了很多版里面最核心的是三部分角色定义你是一个自动整理会议纪要的Agent目标是完成用户指定任务。工具使用规范当你认为需要读取或写入文件时必须调用工具工具调用必须用指定JSON格式一次只能调用一个工具。决策输出规范给出两个选项一是调用工具二是输出最终回答不能同时做。其中“一次只能调用一个工具”非常关键。没有这条约束时模型经常尝试在一个响应里同时调用多个工具比如一边读文件一边写文件这会让执行逻辑变得很复杂。作为最小实现我更希望模型一步步来。参数方面我做了一组对比发现temperature设置为 0 时工具调用最稳定因为不需要创造性发散但最终回答摘要会有一点机械。折中后我把大部分对话流程的温度设为 0.2只对最后写摘要的步骤设为 0.4既能保证工具调用稳定又不太冷冰冰。max_tokens同样需要控制。如果给的max_tokens太小模型的行动决策可能会被截断后半截输出就成了乱码给太大又浪费。我实测下来决策输出通常300-500 token足够最终回答可以放宽到1000左右。3.5 运行结果与效果观察第一次跑通的时候我盯着控制台看了好久。用户输入是一段模拟会议记录“今天讨论了新版本延期问题前端资源不够决定从其他项目临时借调一名开发待办周三前完成接口联调王工负责更新排期。”Agent的执行过程大致是第一步读取原始会议记录文件。第二步生成结构化摘要提取了三个关键待办。第三步调用写文件工具把整理结果保存为meeting_summary.md。第四步输出最终回答告诉用户摘要文件和待办列表已经生成。虽然每一步都很慢中途还出现过一次工具参数写错的情况模型读到错误提醒后自己纠正了路径。那种“模型自己纠错成功”的感觉是学Agent最上头的瞬间。这次实操也让我意识到一个最小Agent并不需要多么复杂的组件一个模型接口、几个工具函数、一个循环、一份提示词就够了。但真实工程里难点会转移到稳定性和边界处理上这也是Day06后半段一直在做的事。4. 两天里踩过的坑与排查方法4.1 模型陷入“嘴上跑火车”的循环第一天下午第一次跑完整流程时我遇到一个特别典型的问题模型一直在输出“我需要先读取文件”“我接下来要做的是……”“好的让我想想怎么处理”看起来逻辑通顺却始终没有输出工具调用JSON。排查下来原因是系统提示词给了太多的“推理空间”。模型倾向于把推理过程写得完整漂亮但这在Agent里是灾难。后来我把输出规范改成了“如果存在可以完成任务的工具必须直接调用只有在不需要任何工具时才能输出回答”同时给了一个“错误示范”和“正确示范”的对比。这个问题立刻缓解。后续还遇到过一种变体模型确实调用了工具但工具完成得很好之后它并不总结而是继续调用同一个工具造成重复劳动。解决方法是要求在观察结果后先判断“任务是否已完成”如果已完成下一轮必须给最终回答。4.2 工具参数解析总是失败这是Day06最磨人的问题。模型返回的工具调用大概是这样{tool: read_file, params: {path: /tmp/会议记录.txt}}但偶尔它会在JSON前后加一堆解释文字比如 “好的我将会读取该文件{...}”。直接用json.loads必然报错。我最初想靠严格提示词解决但实测下来无论提示词多严格模型都可能在边缘情况下夹带私货。最终的解法是双保险解析先用正则找到{到}之间的部分截取出来。再尝试json.loads如果失败把里面的中文引号和转义符修复一遍。同时我在工具调用示例里特意给了“带解释文字”的反例帮助模型理解必须原样输出JSON。这样处理之后解析成功率从最初的70%提升到了95%以上。4.3 长期记忆写不进、读不出做长期记忆功能时我把用户偏好直接存进了一个本地文本文件。一开始遇到的问题是Agent在决策时根本不知道“还有记忆这回事”每次都是直接忽略记忆去问用户或按默认参数执行。后来我把记忆检索做成一个独立工具叫search_memory并把它的描述写清楚“在历史偏好中搜索与当前任务相关的信息如果没有相关信息返回空列表。”这样一来模型在接到一个新任务时会先主动调用记忆检索再决定是否继续问用户。还有一个更隐蔽的问题检索逻辑太粗糙导致把无关偏好也捞了出来。比如用户说“周五开会”记忆里有一条“周五交通拥堵会议时间安排在下午更好”模型就会去调整时间。解决方法是给每条记忆加标签比如time_preference、meeting_habit、file_location、contact_name检索时先按标签过滤再按关键词筛选。这比纯向量检索慢一点但胜在规则完全可控也特别适合小型数据量。4.4 上下文越堆越长费用和延迟直线上升第三天下午我观察到一个现象循环跑得越久单轮响应时间越长。原因很直接我把每一轮的工具观察结果都原封不动地拼进上下文导致上下文越来越长模型处理成本随之飙升。最简单的解法就是做“历史裁剪”。我实现的策略是只保留最近两轮的工具调用和观察结果更早的内容压缩成一段摘要放在开头比如“已完成的操作读取了文件A生成过两版摘要”。这个是纯文本拼接效果已经够用至少不会再出现上下文长度超限的报错。但要注意一点裁剪历史时要保留“重要的中间结论”。例如模型曾经从文件A中提取出“预算为5000元”如果这段观察被裁掉了后续模型可能会忘记这个数字。所以我在裁剪前会先让模型把关键信息同步到记忆文件里再对历史做压缩。这样即使历史丢了Agent也能通过调用记忆检索找回关键信息。4.5 常见问题速查表说白了Agent开发里有大量问题不来自模型本身而来自工程细节。我把这两天遇过的典型问题做成了一张速查表现象根因解决办法模型一直输出分析但不调用工具提示词约束太弱强制要求存在工具时优先调用并给正反示例调用工具时一直在JSON前后加解释文字输出格式不稳定正则截取 容错解析 减少prompt中的干扰项模型做已经完成过的动作缺少对历史观察的利用循环内保留工具结果加“任务是否已完成”判断内存检索结果不相关检索策略太粗加标签过滤再做关键词匹配上下文增长导致延迟升高历史全量保留历史裁剪 摘要压缩 关键信息外置记忆工具返回错误模型反复用同样参数重试错误信息不够具体返回结构化错误写明哪一步失败、参数问题是什么这张表我会继续补充因为很多问题是会反复出现的。每次花时间在工程上做好兜底后面跑新场景时都会轻松不少。5. 下一步要补的功课以及这两天学习最直接的体会5.1 下一步要补的功课两天学完我对Agent的“骨架”已经心里有数但这还只是开始。我最想补的第一块是如何让多个Agent分工协作。现在做的单Agent所有任务都压在同一个模型循环里一旦任务复杂工具数量超过几十个模型的选择困难会明显增加。多Agent分工的好处是每个Agent专注一个子任务决策和工具调用都会更稳定。第二块是系统性评估。我现在验证一个Agent好不好基本靠肉眼观察输出是否合理。这太不严谨了。后面至少要做一批测试用例覆盖正常、异常、边界场景记录成功率、平均调用步数、无效调用比例等指标。只有量化了这些数据才能知道改一次提示词是变好还是变差。第三块是安全与容错。Agent一旦拥有写文件、发消息这类真实操作权限一个错误决策就可能造成实打实的损失。所以后面必须给工具加上权限分级、二次确认、操作日志确保Agent的行为可审计、可回滚。5.2 学习体会工程化细节才是真正的分水岭这两天最直接的体会就是Agent能否跑通决定因素不是模型聪明不聪明而是你愿不愿意把每一个环节的细节抠到位。模型能力再强如果你不告诉它有哪些工具、每个工具怎么用、输出格式是什么它照样会瞎猜。反过来只要你把工具描述、参数校验、循环约束、历史管理这些工程细节做好即便用很基础的模型也能跑出稳定可用的Agent。我见过很多人一上来就追最新框架、最新模型结果核心逻辑没搞懂遇到问题只会换框架换模型。但我的亲身经历是回归到最小实现亲手把每一个模块写一遍才能真正理解Agent为什么是今天这个样子以及各种框架想帮你解决什么问题。最后再分享一个小建议如果你也正在学习Agent请一定给自己留出大量的调试时间。不要指望第一次跑通就是完美结果更不要因为一次失败就怀疑路线。我这两天大概有60%的时间都在盯日志、改参数、调提示词。但正是这些“磨人”的时刻把Agent的原理一点点刻进了我的直觉里。这种手感光看文章和视频是永远得不到的只有自己动手踩几次坑才能真正变成自己的东西。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询