资讯动态

AI Agent实战:从零构建大模型应用的信息助理完整指南

发布时间:2026/10/19 7:34:58 来源:尧图企业网站定制
这两年要是没听过AI Agent都不好意思说自己在做技术。但真正上手的人都知道概念文章满屏都是框架装完又卸载能把自己的Agent从零搭起来、跑通、还能稳定用上一段时间的其实没那么多。这篇文章就围绕“AI Agent构建方法与大模型应用”这条主线把我从零做一个信息助理Agent的全过程、思路和踩坑记录整理出来尽量做到拿过去就能复现。内容不打算做成罗列概念的百科而是按我的实操顺序走先想清楚Agent到底是什么、该解决什么问题再做技术选型和组件规划然后写代码跑通最小闭环最后聊真实场景里的问题排查和成本控制。适合刚接触Agent、看了很多概念但没完整写过一遍的开发者也适合需要给团队做技术预研的技术负责人。看完你能快速判断一个Agent项目从想法到落地到底要过几道坎。1. 想清楚再动手AI Agent到底是什么和普通应用差在哪1.1 从“会聊天”到“会办事”Agent的核心能力到底强在哪普通的大模型应用用户问一句模型回一句。中间没有目标拆解没有外部动作也没有结果验证。Agent不一样它会把一句含糊的话拆成“我要做什么、需要哪些信息、用哪个工具、怎么确认做完了”然后像人一样一步步执行最后把结果回给你。有个很形象的类比普通问答应用像一个电话客服你问一句它答一句答不上来就只会在话术里绕Agent像是一个手里拿着工具箱的办事员你告诉它“帮我把会议纪要整理好顺手排个待办清单”它可以自己决定先看纪要、再提取事项、最后生成清单文件中途如果某个工具失败它还会换个办法重试。所以Agent与普通应用最核心的差距归结起来是三个能力目标感能理解一个多步骤任务而不是只回答单轮问题。工具调用能按照约定格式请求调用外部函数比如查数据库、发消息、写文件。反馈闭环拿到工具返回结果后再决定下一步而不是一次性输出就完事。这个“思考—行动—观察”的循环就是Agent区别于聊天机器人的分水岭。1.2 大模型、提示词、工具调用一张图拆清Agent体系很多人一上来就纠结“哪个框架最强”实际上整个Agent体系拆开看并不复杂大脑大模型负责理解任务、拆解步骤、决定下一步动作。工作流编排循环把思考、行动、观察这个循环反复跑起来直到得出最终结果。手工具就是预定义的函数比如查天气、执行SQL、写文件、发邮件。记忆上下文包括短期对话历史和长期偏好、历史结论。约束护栏包括最大步数、工具白名单、输出格式校验、权限确认。你可以想象一条流水线用户说了一句话大脑拿到这句话后开始推理如果发现需要实时信息或外部操作就生成一个结构化请求交给手去执行。手执行完把结果塞回对话大脑看到结果继续推理直到认为自己已经把任务解决才生成面向用户的最终回复。下面是一次典型任务的全过程用户说“帮我查一下本周三下午有没有空会议室有的话预定一间。”大脑判断需要查会议系统于是调用工具query_meeting_rooms参数是“本周三下午”。工具返回结果有三间空闲会议室。大脑看到结果继续规划需要预定其中一间于是调用工具book_meeting_room参数是会议室编号。工具返回预定成功。大脑生成最终回复“已帮你预定本周三下午某会议室。”这六步里模型被执行了多次工具被调用了两次每一步都依赖上一步的返回结果。这就是Agent的典型工作方式。1.3 Agent不是万能药哪些需求适合用Agent解决了解Agent能做什么之后更要知道什么场景不该硬上。我从实际项目里总结出几条判断标准。适合用Agent解决的问题一般具有这些特征多步推理比如“分析近30天的销售数据找出异常原因并生成报告”需要数据查询、异常检测、文本生成多个环节。实时信息比如查天气、查库存、查订单状态模型自身知识库覆盖不了。跨系统操作比如在工单系统建单、在日历里排期、在文档库检索后归档。结果需要验证比如先生成SQL再执行执行结果再回填报告。不适合用Agent的场景也很明显高频低延迟接口比如用户点了按钮就要立刻返回Agent多轮循环的延迟容易超时。强确定性流程比如资金结算、订单状态流转这类场景要求步骤固定、结果可审计交给规则引擎更稳而不是让模型临时发挥。单次成本敏感每多一轮调用都是在烧token如果任务其实一句就能答完没必要上Agent。数据安全约束极高外部模型调用可能把数据带出内网除非走私有化部署否则要慎重。我个人的判断方法是先问自己这个需求如果交给一个新人他能不能按一套书面流程做下来如果能而且步骤里需要查外部系统、需要根据中间结果调整动作那就适合Agent如果答案只是“查一下资料回答我”那做普通应用就够了。2. 动手前的关键设计目标拆解、模型选型与组件准备2.1 把需求拆成“Agent能听懂”的步骤是成败的关键很多人一上来就写代码结果写了一半发现模型不听指挥。问题往往不在模型而在需求从来没被拆到模型能理解的程度。我习惯先做一张流程拆解表把口头需求变成可执行的步骤。拿我实际做的信息助理为例用户的需求是“把今天收集到的资料整理成摘要并生成一个待办清单”。看起来很自然的一句话落到Agent层面需要拆成这样步骤具体动作成功标准失败兜底1获取今天新增的资料文件拿到文件列表或内容告诉用户“今天没有新资料”2对资料内容做摘要输出每条资料的核心结论单条资料过长时截断再摘要3从摘要中提取待办输出结构化待办列表无明确事项时提示用户4生成清单并写入本地文件返回文件路径写入失败时返回错误原因拆完这个表你才能真正定义工具边界Agent需要哪些工具每个工具接收什么参数返回什么结构哪些操作允许自动执行哪些需要用户确认这里有个关键点不要把完整指令塞给模型让它自由发挥而是把流程的骨架固定住让模型在骨架里做决策。比如“先检索、再摘要、再生成待办、最后确认写文件”这个顺序是规则层面确定的模型负责的只是每一步里的具体内容选择。这样既利用了模型的灵活性又保证结果可预期。2.2 大模型选型怎么挑一个适合做Agent的底座选模型是很多人最容易纠结的环节。我的原则很简单做Agent稳定性优先于单点聪明。一个对话能力很强但在函数调用场景下经常漏参数、格式不稳定的模型会让你排查到崩溃反过来一个略笨但每次输出都能严格符合要求的模型反而是好选择。选型时我一般关注这几个维度维度说明考察方法上下文长度决定能塞多少历史信息和工具返回结果压测多轮任务不丢早期内容工具调用支持是否原生支持函数调用、参数校验是否严格写20个不同参数类型做回归推理稳定性面对同一任务多次执行结果是否一致同一输入跑5次看差异单位成本输入和输出token的单价用典型任务估算并发成本限流与延迟并发上限、首字延迟压测脚本实测有一个选型计算技巧很多人忽略。我通常会把一个典型Agent任务跑一遍统计平均轮数和token消耗然后反推成本。比如平均每轮输入5000 token、输出500 token一个任务平均需要5轮调用那么这个任务单次消耗大约5000 500× 5 27500 token。如果一天要跑100个任务就是约275万token的日消耗再乘以服务商的单价立刻能算出这个Agent上线后每月烧多少钱。这个账在选型阶段就要算清楚而不是等月底看账单。2.3 必备组件记忆、工具接口、编排框架的真实含义很多文章把记忆、工具、框架讲得很玄其实就是三样东西。记忆分两层。短期记忆就是对话上下文直接在消息数组里保留历史模型天然能看到。长期记忆则是把历史偏好、历史结论存起来下次任务开始时检索相关片段回填到上下文。实现长期记忆最简单的方式就是选一个向量库把历史信息向量化存储新任务来时用相似度检索。别一开始就上复杂的记忆系统先跑通短期记忆再说。工具接口的本质是“模型的说明书”。模型并不知道你的系统里有哪些函数你必须在请求里把函数名字、参数、用途告诉它。工具描述写得好不好直接决定模型调用得对不对。比如一个保存笔记的工具description里写“保存笔记”和“当用户明确要求记录一段文字时保存为本地文件文件名为用户指定的名称内容为用户的原文”后者明显更能让模型正确决策。所以写工具接口的本质是写文档不是写代码。编排框架解决的是循环调度、上下文整理、工具注册这些重复劳动。我的建议是第一次做Agent不要上重型框架先手写一个循环比如下一章那个50行的主循环。等你理解Agent的工作流之后再引入框架也不迟。框架能帮你省事但如果你不知道它背后循环在干吗出了错根本无从排查。3. 从0到1实现一个可用Agent完整实操3.1 场景定义先做一个能跑通全流程的“信息助理”这一章我们做一个最小可用的“信息助理Agent”。目标定得不高能覆盖三类任务纯知识问答不需要工具模型直接回答。实时信息查询查当前日期、计算数学表达式必须调用工具。外部操作把用户指定的内容保存为本地笔记文件涉及文件系统操作。为什么选这三类因为它们分别覆盖了Agent的三种典型动作纯推理、工具查询、外部动作。跑通这三类你就能理解Agent循环的核心逻辑后续往任意业务场景扩展都只是加工具的问题。工具清单设计如下工具名功能参数返回get_current_date返回当前日期和周几无字符串calculate计算数学表达式expression字符串save_note保存笔记到本地文件filename, content字符串3.2 系统提示词的写法把约束写进上下文系统提示词是Agent的“岗位说明书”。我见过太多人随便写一句“你是一个聪明的助手”结果模型行为全靠运气。可靠的写法是把规则分条列清楚尤其要写明“什么时候用工具什么时候不用”。下面这段是我调过几版后稳定可用的模板你是信息助理Agent。你会收到用户的一句话任务请把它拆解成执行计划再按计划完成。 规则 1. 当任务仅需要自身知识就能回答时直接回答不要调用任何工具。 2. 当任务涉及实时信息或外部操作时必须调用对应工具不要凭空编造结果。 3. 每次工具调用之后必须根据工具返回的内容继续推理不得虚构执行结果。 4. 工具执行失败时如实告诉用户失败原因并给出下一步建议。 5. 最终回答控制在200字以内关键信息可以用简短列表呈现。 6. 仅使用本场景提供的工具禁止自主想象其他操作。这六条里最容易被忽略也最关键的是规则3。很多Agent翻车就是因为模型在工具返回一堆报错后完全无视错误假装操作成功了。写明“基于返回结果继续推理”实际上是在约束模型的幻觉倾向。规则1也重要它防止模型为了“展示能力”而拿鸡毛蒜皮的问题也去调一次工具白白浪费时间。3.3 核心代码骨架思考—行动—观察循环的实现下面给出核心代码骨架。我刻意不依赖任何重型框架只用一个Python主循环方便你理解每一步发生了什么。import json import requests from datetime import datetime API_KEY your-api-key BASE_URL https://your-llm-api.example.com/v1/chat/completions MODEL_NAME your-model-name SYSTEM_PROMPT ( 你是信息助理Agent。你会收到用户的一句话任务请把它拆解成执行计划再按计划完成。\n 规则\n 1. 当任务仅需要自身知识就能回答时直接回答不要调用任何工具。\n 2. 当任务涉及实时信息或外部操作时必须调用对应工具不要凭空编造结果。\n 3. 每次工具调用之后必须根据工具返回的内容继续推理不得虚构执行结果。\n 4. 工具执行失败时如实告诉用户失败原因并给出下一步建议。\n 5. 最终回答控制在200字以内关键信息可以用简短列表呈现。\n 6. 仅使用本场景提供的工具禁止自主想象其他操作。 ) def llm_call(messages, tools): payload { model: MODEL_NAME, messages: messages, tools: tools, tool_choice: auto, } resp requests.post( BASE_URL, headers{Authorization: fBearer {API_KEY}}, jsonpayload, timeout60, ) resp.raise_for_status() return resp.json()[choices][0][message]工具定义部分包括每个函数本身的实现和它的schema描述def get_current_date(): return {ok: True, date: datetime.now().strftime(%Y-%m-%d %A)} def calculate(expression: str): try: # 注意生产环境校验表达式内容防止恶意代码 result eval(expression, {__builtins__: {}}, {}) return {ok: True, result: str(result)} except Exception as e: return {ok: False, error: str(e)} def save_note(filename: str, content: str): try: with open(filename, w, encodingutf-8) as f: f.write(content) return {ok: True, path: filename} except Exception as e: return {ok: False, error: str(e)} TOOLS [ { type: function, function: { name: get_current_date, description: 返回今天的日期和星期。当用户询问当前日期、今天几号等实时信息时调用。, parameters: {type: object, properties: {}}, }, }, { type: function, function: { name: calculate, description: 计算数学表达式比如加减乘除。当用户要求计算时调用表达式必须为纯数学公式。, parameters: { type: object, properties: { expression: {type: string, description: 数学表达式如(1234)*5}, }, required: [expression], }, }, }, { type: function, function: { name: save_note, description: 把一段文字保存为本地笔记文件。当用户明确表示要记录、保存笔记时调用。, parameters: { type: object, properties: { filename: {type: string, description: 文件名需包含.txt后缀}, content: {type: string, description: 要保存的正文内容}, }, required: [filename, content], }, }, }, ]核心主循环就是“思考—行动—观察”的翻译def execute_tool(name, arguments): if name get_current_date: return json.dumps(get_current_date(), ensure_asciiFalse) if name calculate: return json.dumps(calculate(arguments[expression]), ensure_asciiFalse) if name save_note: return json.dumps(save_note(arguments[filename], arguments[content]), ensure_asciiFalse) return json.dumps({ok: False, error: funknown tool: {name}}) def run_agent(user_input, max_steps5): messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input}, ] for step in range(max_steps): message llm_call(messages, TOOLS) messages.append(message) if message.get(tool_calls): for tc in message[tool_calls]: fn tc[function] args json.loads(fn[arguments]) print(fstep {step}: invoke {fn[name]}, args{args}) result execute_tool(fn[name], args) messages.append({ role: tool, tool_call_id: tc[id], content: result, }) else: return message[content] return 已达最大步数任务提前中止请检查是否出现循环。这个循环做的事很简单每次调模型如果模型认为需要调用工具就执行工具并把结果塞回消息列表如果模型认为任务完成就直接返回文本。整个过程循环进行直到拿到最终答案或超过最大步数。3.4 工具注册与调用让Agent真正拥有“手”工具注册看起来只是填参数但这里面的坑非常深。最关键的是工具描述的质量。我对比过两个版本的描述版本一description: 保存笔记。模型经常在用户只是提到“记录一下”时就去调用它但用户其实只是随口说。版本二description: 把一段文字保存为本地笔记文件。当用户明确要求记录、保存笔记时调用否则不要调用。文件名需包含.txt后缀内容为原文。。调用准确率明显提升。原因在于模型本质上是通过description来判断“什么时候用我”。你把触发条件写得越清晰它的判断就越准。如果你的工具在“不满足条件时坚决不调用”的说明模型反而会更容易学会克制。参数描述同样重要。比如calculate的参数如果只写“expression”模型可能传入今天的天气是什么这种非表达式内容。补上“必须为纯数学公式如(1234)*5”之后错误少了很多。所以工具注册表写的不是JSON是给模型的说明文档偷懒不得。另一个容易被忽略的点是返回值。模型需要从工具返回值里提取关键信息所以返回值要尽量结构化。我统一用{ok: true/false, ...}的形式让模型一眼能看懂成功还是失败。失败时返回{ok: false, error: ...}模型就会进入“报告失败并提供建议”的正确分支。3.5 成本与安全给Agent装上护栏Agent跑起来之后最怕的不是它不干活而是它“胡干活”。我习惯在代码净化阶段装上几道护栏。最大步数限制是必须的。模型在复杂任务里偶尔会陷入自我对话的死循环没有步数上限一次请求能把你的token烧穿。上面代码里的max_steps5就是在做这件事。工具白名单也很关键。模型只能调用你注册过、并且允许它在当前场景下使用的工具。如果业务系统里有删除、转账这类敏感操作最好单独拆分出一个子Agent来执行并且在调用前增加二次确认。我实践过一种简单的确认机制当Agent准备调用敏感工具时不让它直接调用而是先输出一句“准备执行XX操作请回复确认”。用户说确认后才在下一轮真正执行工具。这个机制多花一轮对话但能避免大量误操作。输出校验同样别省。在最终回复返回给用户前检查是否包含必备字段、是否为空、格式是否可解析。我在一个报告生成Agent里加过最基础的“输出长度校验”如果模型回复超过了设定阈值就强制让模型重写效果很明显。Agent的输出是程序化入口和用户入口的混合校验是最后一道关。日志记录是所有护栏里最基础也最重要的。每一步的系统提示词、用户输入、模型输出、工具返回全部落盘记录。出了问题先查日志而不是先猜模型哪里“犯傻”。4. 常见问题与排查技巧实录4.1 Agent答非所问意图识别跑偏的四个原因我调试Agent时候最常遇到的就是模型答非所问。表面看是模型“笨”其实绝大多数情况是设计问题。原因一系统提示词太“作文”化。写了一大段优美描述但没有明确的规则模型靠猜。对策把提示词分条明确“必须”“不得”。原因二工具描述过于宽泛。比如“查询信息”这种描述模型不知道查询什么、什么时候查。对策写清触发条件和触发时机。原因三历史信息干扰。对话轮次多了以后模型分不清用户当前问的是什么问题和之前的问题有关还是无关。对策在最后一次用户输入前面加一句“当前最新问题”或者必要时只保留最近几轮。原因四没有固定回归用例。今天测两个问题觉得不错过几天调了提示词又退化了自己还没发现。对策维护一个至少20条的测试集每次改动后跑一遍。4.2 工具调用连环出错从超时、参数错到循环死锁工具调用出错是最消耗排查精力的环节常见问题有三种。参数类型错误。模型传入的参数偶尔会多一个字段或类型不对。我的处理方式是在execute_tool里用try-except捕获异常把错误结构化返回给模型。模型看到错误信息后很多时候自己能纠正重试。工具超时。如果一个工具内部请求外部系统超过3秒Agent整个循环都在空转。我在工具内部都加了显式超时设置并且把超时信息告知模型比如返回{ok: false, error: database timeout, suggest: retry later or use local cache}。这个suggest字段很有用模型会基于它给出合理的用户提示。循环死锁。典型表现是模型反复调用同一个工具每次返回同样错误却不停重试。最常见的原因是没有步数上限或者工具错误信息不够结构化让模型不知道换路。我给工具统一返回ok字段就是解决这个问题模型看到ok: false就会走“失败反馈”分支而不是继续莽撞重试。排查工具循环问题时我建议按这个顺序来先打印每一步的完整请求和响应再用固定的参数直接调工具函数排除工具自身问题最后检查系统提示词里是否把工具的触发条件写得足够明确。4.3 Token预算失控如何不让Agent烧钱Agent比普通问答应用贵这是必然的但贵到什么程度可控取决于你怎么设计。照上面的例子算一笔账一个典型工具型任务平均每轮输入5000 token、输出500 token跑5轮单任务消耗约27500 token。一天100个任务就是275万token。如果服务和上下文更长这个数字还会涨。所以Agent上线前一定要做成本估算。我用的降本手段按效果排序手段说明效果精简系统提示词去掉废话只保留规则性内容每轮能省几百到上千token截断历史消息只保留最近N轮或按token阈值裁剪显著降低每轮输入长度工具结果摘要长返回先摘要成关键信息再回填上下文长期任务收益极大结果缓存相同或相似问题直接返回缓存不走模型中高频任务明显大小模型结合简单步骤用便宜小模型复杂推理用大模型整体成本下降30%以上我做过一个数据报表Agent起初每轮都把完整日志原文塞进上下文一次任务轻松烧掉几万token。后来改成工具结果先做“信息压缩”只提取关键数值和结论再回填同样的任务token消耗降到原来的三分之一。所以上下文里不要什么都放模型需要的只是能决策的那部分信息。5. 我踩过的几个坑和后续扩展方向5.1 三个印象深刻的翻车现场第一个翻车现场是我在系统提示词里写了“如果有必要可以调用工具”。结果模型几乎每个问题都先调一次工具哪怕用户只是问“你好”。后来改成规则1明确“仅当任务需要实时信息或外部操作时才调用工具”情况才正常。写提示词一定要把触发条件收窄给模型留的“自由裁量权”越少越好。第二个翻车现场是工具报错时直接把Python异常堆栈返回给模型。模型看到一长串Traceback开始一本正经地分析“这个错可能是环境变量问题建议检查服务器配置”实际上什么都不懂。后来我把所有异常都包装成{ok: false, error: human-readable message}模型才能给出正常人能听懂的建议。第三个翻车现场是跑一个长会话Agent时没限制上下文长度。到第15轮历史消息已经逼近模型窗口上限请求超时整个任务失败。后来我加了“历史消息按token截断只保留最近10轮系统提词词”的逻辑长会话才稳定下来。这个教训提醒我Agent的上下文管理不是优化项是必需品。5.2 从“能跑”到“好用”还能加的能力跑通最小Agent之后有几个方向值得继续扩展按性价比排序。长期记忆是第一个建议加的。把用户的历史偏好存进向量库新任务开头先检索相关记忆。比如用户多次说过“报告要包含环比”下次生成报告时模型就会自动带上体验提升非常明显。评估集是第二个建议。建一份固定测试集包含正常任务、边界任务、误导性任务每次调完提示词或工具后跑一遍记录通过率。没有这个评估集你会发现每次优化都是“拆东墙补西墙”。多Agent协作是更高级的方向把任务拆成规划、执行、审核三个角色。规划Agent负责拆解执行Agent负责调工具审核Agent负责检查结果。优点是可以给不同角色配不同模型和预算缺点是复杂度上升很快。建议先把单Agent做到稳定再考虑。可观测性也很值得做。把每轮循环的输入输出、工具调用、耗时、token消耗汇总成结构日志最好再画成可视化面板。我之前排查问题全靠打印后来做了一个简单的日志面板定位效率至少翻一倍。写在最后我在实际构建里最大的体会是Agent开发不是提示词工程加接口调用的简单叠加它更像在开发一个“总会绕你弯子”的协作系统。你要把系统提示词当代码维护把工具定义当接口文档设计把模型当成一个能力很强但偶尔犯错的同事来管理该给流程给流程该加护栏加护栏。真正跑通一个Agent后你会发现它最大的价值其实不是“聪明”而是能按照你的规则把脏活累活干完并且每一步都能被追溯、被修正。最后分享一个缩小试错成本的建议第一版一定要小一个场景、三个工具、五十行主循环跑通闭环后再逐步加记忆、加评估、加多角色这条路比一开始就上重型架构稳妥得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑