很多刚开始接触 AI智能体Agent的朋友都有同一种困惑看了几十篇科普文章知道 Agent 是目前大模型落地最热的方向可真要自己动手做一个又不知道从哪里切入。更常见的情况是——用提示词让大模型扮演一个助手发现它只是换个方式聊天给它接入一个搜索接口又发现它答非所问、绕来绕去完全没有网上说的那么聪明。说实话这些问题的根源通常只有一个把 Agent 理解成了加了工具的聊天机器人却没有理解它的运行机制和设计约束。这篇文章我会把 Agent 从概念到原理、从最小实现到工程化落地完整讲一遍。内容包括Agent 与大模型原生接口的本质区别、四大核心机制规划、记忆、工具、反思、一套通用技术架构、一个不依赖框架的最小可用 Agent 代码实现、主流框架选型、常见进阶方向以及我在实际调试中最常遇见的坑和规避方式。无论你是刚接触编程的初学者还是已经写过不少提示词的开发者按这条线走下来基本能把入门到精通的主干打通。1. 从会聊天到会干活Agent到底比大模型多做了什么1.1 大模型接口只是嘴Agent 是脑子加上手脚先把一个误区拆掉很多人以为调用了大模型的对话接口就等于做了一个 Agent。其实不是。你直接向大模型问今天天气怎么样它能给你一段描述但如果它本身没有联网能力这段描述大概率是编的。你把大模型接口当成一个会说话的大脑它只能基于训练时见过的数据做预测无法主动获取新信息也无法对你的电脑、文件、数据库产生任何实际操作。Agent 则不同。它除了拥有这个大模型作为决策核心之外还多出了几个关键组件能感知环境读取文件、查询接口、接收用户指令、能执行动作调用函数、写入文件、操作软件并且能根据执行结果反复调整下一步计划。打个比方大模型接口相当于一个只有嘴巴的专家而 Agent 是给这位专家配上了眼睛、耳朵和手还给他一张办公桌和一个工作流程。它不再是回答你的问题而是完成你交给它的任务。这里有一个很关键的认知Agent 的能力上限其实不取决于大模型多聪明而取决于你交给它的工具多不多、工具描述准不准、控制流程稳不稳。我见过不少人用一个很大的模型却因为工具描述写得含糊Agent 频繁调用错误参数最终效果反而不如一个小模型搭配精心设计的工具层。1.2 一个最简单的对比案例没有工具和拥有工具我用一个最直白的例子说明。假设任务是查一下当前日期对应的农历节气。纯大模型调用它会根据训练数据中的节气规律做推断如果你问的是 2025 年之后的某个日期它可能会给出一个错误的农历日期。因为它没有日历计算能力也没有查询工具。一个最小 Agent它接收到任务后先规划——我需要知道今天的农历信息或者至少知道今天的公历日期接着调用一个获取当前日期的工具再把工具返回的结果交给大模型由大模型结合常识做下一步判断。如果它手头还有农历转换工具它就直接调用没有的话它会告诉用户我只能确认今天是几月几号农历节气需要额外工具。差别就在这里纯大模型是在猜Agent 是在查、算、做。这个先规划、再调用、再观察结果、再决策的闭环就是 Agent 的灵魂。1.3 智能体的运行闭环规划、行动、观察如果只用一句话概括 Agent 的运行过程我会说它是一个规划-行动-观察的循环。规划大模型根据用户目标拆解出当前第一步应该做什么。行动选择一个工具并传入参数执行某个具体动作。观察拿到工具返回的结果把结果作为新的上下文交给大模型。重复直到大模型认为目标已经达成输出最终答案或达到轮次上限终止。这个循环听起来简单但工程上每一个环节都有大量细节。比如规划时模型可能拆错步骤行动时参数可能格式不对观察时返回结果太长把上下文撑爆。我后面会专门用一章来演示一个最小实现到那一步你再回头看这一节会理解得更透。2. 剥开Agent的核心机制规划、记忆、工具与反思2.1 规划把大目标拆成可执行的小步骤规划是 Agent 的第一个核心能力也是它看起来聪明的主要原因。面对一个模糊指令比如帮我把这份销售数据整理成周报Agent 需要自己决定先做什么、后做什么。在早期的纯提示词方案里这个能力靠的是在 system prompt 里写请一步一步思考。现在更工程化的做法是让模型输出结构化的计划 JSON或步骤列表再由控制器逐条执行。这里有一个容易被忽略的重点规划不是一次性的。初始计划往往很粗糙Agent 在执行过程中发现某一步缺少数据、某个工具报错就需要重新规划。所以更合理的说法是动态规划——每一步都在重新评估剩余任务。实操建议在提示词中明确告诉模型不要一次性输出完整代码或完整答案先输出下一步动作。这会显著减少模型想当然地跳过中间步骤的问题。2.2 记忆短期工作记忆与长期记忆记忆是 Agent 区别于无状态接口的重要组件。你可以把大模型上下文窗口理解成 Agent 的短期工作记忆里面装着当前任务的所有中间过程。但上下文窗口是有限的一旦塞进太多历史模型会忘了最初的目标或者被无关信息干扰。长期记忆则用来解决跨会话、跨任务的问题。常见做法有两类向量记忆把重要的事实、对话记录、工具结果切块后做嵌入向量存入向量数据库每次任务开始时检索出最相关的几个片段拼进上下文。摘要记忆定期让大模型对已有对话做摘要压缩用摘要替代原始长文本从而节省上下文空间。我在实际项目中更偏向两者结合短期对话用摘要长期知识用向量检索。这也是很多成熟的 Agent 框架默认的方案但它不是银弹——记忆内容的噪声会直接影响 Agent 的决策质量后面我会专门讲上下文污染这个坑。2.3 工具Agent 能力的边界由工具决定没有工具的 Agent 只是高级聊天机器人有了工具才变成数字员工。工具可以是函数、API、命令行程序、代码解释器甚至是另一个 Agent。设计工具时有一个原则值得刻在桌上工具描述决定工具命运。模型只能通过你写的描述来理解这个工具是干什么的、参数怎么填、什么时候该用。我曾经遇到一个案例一个获取天气的工具描述里只写了获取指定城市的天气没有说明返回格式。结果 Agent 把工具输出直接当成了自然语言答案返回给用户完全没做任何加工用户看到的就是一段 JSON。后来我把描述改成获取指定城市的当前天气返回结构化 JSON请根据 JSON 生成自然语言回答效果立刻就好多了。工具的数量也要克制。给 Agent 挂上二三十个工具不仅增大模型选错工具的概率还会消耗大量上下文空间去解析工具定义。我推荐先挂最少必需的工具跑通流程后再逐步增加。2.4 反思让模型自己评价自己反思是 Agent 进阶的典型标志。它指的是在 Agent 执行完一轮或多轮后让大模型重新审视自己的输出检查是否达成了用户目标、有没有更优路径、哪些步骤是多余的。一种简单的反思实现是两步走先让 Agent 正常执行任务拿到结果再把这个结果和任务目标单独发送给大模型要求它以评审员身份指出问题并提出改进建议。如果发现关键错误就让 Agent 重新执行。听起来很美好但反思会增加至少一倍的大模型调用次数和延迟而且有时候模型会过度反思——明明结果是对的却因为想要显得更严谨把正确的答案改错。我个人的经验是反思只用于高风险场景比如代码生成、财务计算、用户可见的正式文案对于查个时间这类低风险任务完全没必要。3. Agent的经典技术架构大脑、感知与行动的分工3.1 大脑负责决策的大模型Agent 的架构通常可以抽象成三个模块大脑、感知、行动。大脑就是核心大模型它负责理解用户意图、拆解任务、决定调用什么工具、判断任务是否完成。选择大脑模型时不能只看参数规模更要关注三点指令遵循能力能不能严格执行你设定的输出格式比如 JSON。工具调用能力能不能正确理解工具描述并生成符合要求的参数。上下文长度能不能容纳足够多的中间过程和工具返回。在实验阶段我建议先用成本较低的模型把流程跑通再换更强模型看效果提升。这样可以避免一开始就用昂贵模型排查流程问题烧钱且难以定位。3.2 感知把环境信息变成模型能理解的文本感知模块负责把外部世界的非结构化信息转换为大模型可以处理的文本。比如读取 PDF、Word、Excel 后提取文本内容调用 API 拿到 JSON 后截取关键字段做网页抓取后过滤掉导航栏和广告区只保留正文识别图片的 OCR 结果。这部分看似不起眼却往往决定 Agent 的体验。大模型的上下文有限感知模块做得好的标准是让模型只看到与当前任务相关的信息而不是把原始数据一股脑塞进去。我习惯把感知模块设计成先粗采、再过滤、后压缩三步先拿到完整数据再按关键词或相关性过滤最后用摘要或结构化格式压缩。3.3 行动连接外部世界的执行器行动模块把大模型的决策变成真实世界的变化。它通常是一个工具注册表加一个执行器工具注册表每个工具包含名称、描述、参数 schema、执行函数。执行器接收模型输出的工具调用指令完成参数校验后执行对应函数并捕获返回值或异常。行动模块在工程上最重要的不是能执行而是执行得安全。如果一个 Agent 可以自由执行任意 shell 命令、删改任意文件那它就是一把没有保险栓的枪。我在设计行动模块时一定会加三层护栏参数白名单只允许特定格式、路径限制只能在指定目录写文件、权限校验危险操作需要用户二次确认。3.4 控制流单循环、多角色与人工介入Agent 的控制流决定了模块之间如何协作。最简单的控制流是单 Agent 循环用户输入 → 大脑规划 → 感知/行动 → 观察 → 循环 → 输出。这是绝大多数入门项目的形态。再往上一级是多角色协作把任务拆给一个负责搜索的 Agent、一个负责分析的 Agent、一个负责写报告的 Agent由它们通过消息传递配合。复杂系统中还会加入人工介入节点当 Agent 检测到自身置信度过低、或执行到关键决策节点时暂停并请求人工确认避免不可逆的误操作。控制流不是越复杂越好。多角色协作虽然听起来高级但通信成本和错误传递风险也成倍增加。我在生产项目里见过太多两个 Agent 互相纠错把任务跑了二十轮还没结束的案例。建议大部分真实业务先从单 Agent 少量工具开始确有必要再引入多角色。4. 手写一个最小可用Agent不依赖任何框架也能跑通4.1 准备工作与环境搭建这一章是整篇文章里最能帮你建立手感的部分。我不打算直接用某个重量级框架而是带你在 Python 里从零写一个最小可用的 Agent。它能让你真正理解循环从哪来到哪去之后再去用现成框架就有底气了。环境准备只需要两样东西Python 3.9 以上环境以及一个大模型 API 的访问权限。大模型服务需要支持 OpenAI 兼容的 chat completions 格式现在绝大多数商业模型服务都支持不需要额外安装特殊 SDK直接用 requests 就可以。把密钥放到环境变量里不要直接写进代码。import os import json import requests import ast import operator from datetime import datetime API_KEY os.environ.get(LLM_API_KEY, your-api-key) BASE_URL os.environ.get(LLM_BASE_URL, https://your-model-service.example.com) MODEL os.environ.get(LLM_MODEL, your-model-name)4.2 定义工具层函数就是最原生的工具在最小实现里工具就是一个个普通函数再加上一段描述文本和参数说明。我先定义三个最常见的工具获取当前时间、安全计算器、抓取网页标题。def get_current_time(): return {result: datetime.now().strftime(%Y-%m-%d %H:%M:%S)} def safe_calculate(expression: str): 只允许基础四则运算避免 eval 任意代码执行的风险 allowed_ops { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.Pow: operator.pow, ast.USub: operator.neg, } def _eval(node): if isinstance(node, ast.Expression): return _eval(node.body) if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)): return node.value if isinstance(node, ast.BinOp) and type(node.op) in allowed_ops: left _eval(node.left) right _eval(node.right) return allowed_ops[type(node.op)](left, right) if isinstance(node, ast.UnaryOp) and type(node.op) in allowed_ops: return allowed_ops[type(node.op)](_eval(node.operand)) raise ValueError(Expression not allowed) try: parsed ast.parse(expression, modeeval) value _eval(parsed.body) return {result: value} except Exception as e: return {error: str(e)} def fetch_page_title(url: str): try: resp requests.get(url, timeout10, headers{User-Agent: Mozilla/5.0}) resp.raise_for_status() text resp.text start text.find(title) end text.find(/title) if start ! -1 and end ! -1: return {result: text[start 7:end].strip()} return {result: no title tag found} except Exception as e: return {error: ffetch failed: {e}}注意我故意没有把危险工具比如删除文件、执行系统命令放进去。这是刻意为之在最小实现里直接屏蔽危险能力比事后加校验要安全得多。4.3 实现 ReAct 循环思考-行动-观察接下来是最核心的部分ReAct 循环。我让大模型每一步都输出一段 JSON包含思考过程、需要调用的工具名、参数、最终答案。主循环判断如果返回的工具名不为空就执行工具把观察结果拼回消息列表继续下一轮如果工具名为空说明 Agent 认为任务完成返回最终答案。TOOLS { get_current_time: { description: 获取当前日期和时间无参数, func: get_current_time, }, safe_calculate: { description: 计算一个数学表达式的值传入 expression 字符串例如 3.14 * 2, func: safe_calculate, }, fetch_page_title: { description: 抓取一个网页的标题传入 url 字符串, func: fetch_page_title, }, } def llm_call(messages): payload { model: MODEL, messages: messages, temperature: 0.2, response_format: {type: json_object}, } resp requests.post( f{BASE_URL}/chat/completions, headers{Authorization: fBearer {API_KEY}}, jsonpayload, timeout60, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content] def run_agent(user_query: str, max_steps: int 5): system_prompt f 你是一个任务执行型 Agent。你可以使用以下工具 {json.dumps({name: info[description] for name, info in TOOLS.items()}, ensure_asciiFalse)} 请严格输出 JSON字段包括 - thought: 你对当前情况的思考 - tool: 要调用的工具名如果任务已完成则为 null - tool_input: 工具参数字典 - final_answer: 最终回答如果还没完成则为 null 流程要求 1. 先判断是否需要工具需要就调用不需要就直接回答。 2. 调用工具后根据观察结果继续思考直到任务完成。 messages [ {role: system, content: system_prompt}, {role: user, content: user_query}, ] for step in range(max_steps): content llm_call(messages) messages.append({role: assistant, content: content}) print(f--- Step {step 1} ---) print(content) try: action json.loads(content) except json.JSONDecodeError as e: return {error: f模型输出不是合法 JSON: {e}, raw: content} if action.get(final_answer): return action[final_answer] tool_name action.get(tool) tool_input action.get(tool_input) or {} if tool_name and tool_name in TOOLS: tool_result TOOLS[tool_name][func](**tool_input) messages.append({ role: user, content: f观察结果{json.dumps(tool_result, ensure_asciiFalse)} }) else: messages.append({ role: user, content: f观察结果工具 {tool_name} 不存在请换一个可用工具。 }) return {error: 达到最大轮次任务未完成, messages: messages}如果你把这段代码保存为 agent_minimal.py然后运行下面的测试就能看到完整的思考与行动循环if __name__ __main__: result run_agent(今天是星期几另外帮我计算 123 * 456 的结果然后访问 https://example.com 抓取标题。) print(最终答案:, result)你会发现模型会按顺序调用多个工具再把每个工具的返回结果汇总成一段自然语言。这个多工具接力的效果是单纯提示词很难稳定做到的。4.4 加入安全护栏轮次上限与参数校验上面的最小实现里已经包含了两个关键护栏轮次上限 max_steps防止 Agent 无限循环工具白名单只允许已注册的函数被调用。但还有几个细节需要补强参数校验。在上面的 safe_calculate 里我已经用 AST 限制了表达式类型避免 eval 被注入恶意表达式。实际接入任意工具时一定要对字符串参数的长度、格式、路径范围做校验。观察结果截断。如果工具返回了一个 10 万字的文档直接塞进上下文会把后续轮次全毁掉。建议在把观察结果拼入 messages 之前超过 2000 字符就做截断保留开头和结尾。异常豁免。工具执行一旦抛出未捕获的异常可能导致整个 Agent 崩溃。所以我习惯把所有工具函数统一包一层 try_except把任何异常转换成结构化字符串返回给模型。提示千万别为了省事跳过这一步。在真实的 Agent 工程里绝大部分翻车事故都发生在工具返回了意外的内容和模型输出了不合法的 JSON这两种情况上。5. 主流Agent框架对比什么场景该选什么5.1 为什么建议先手写再上框架既然市面上有各种好用的框架为什么我还要你先手写一遍原因很简单框架会把循环、记忆、工具调用都封装得非常好但也会把关键机制藏进黑盒。一旦出现Agent 跑偏或上下文爆炸的问题不懂底层的人只能瞎调参数而自己写过一遍循环的人会立刻想到是不是观察结果没有截断是不是工具描述不清晰是不是某一步模型输出了非法 JSON所以我的建议是先实现一遍最小 Agent理解透 ReAct 循环的每一步再用框架提升效率。如果你已经对原理很熟了可以直接跳到框架选型。5.2 四类框架侧写编排型、轻量函数型、浏览器自动化型、可视化工作流型我按适用场景把框架大致分成四类这样选型会更清晰类型典型特征适合人群主要短板编排型提供完整 Agent 生命周期工具注册、记忆管理、多角色协作、回调机制需要构建复杂多工具任务、多个角色协作的开发者学习曲线陡抽象层多排查问题绕轻量函数型代码侵入小把工具循环封装成函数随时可嵌入现有项目想在已有业务代码里快速加入 Agent 能力的团队生态相对有限复杂编排要自己写浏览器自动化型通过视觉或 DOM 操作接管浏览器能点击按钮、填表、抓取页面需要自动化网页操作、数据采集的工程师稳定性依赖页面结构维护成本偏高可视化工作流型通过拖拽节点配置流程适合业务人员快速搭建非程序员、运营人员快速做 demo灵活性受限复杂条件判断难实现从我的经验看入门学习和 for 实验项目优先选轻量函数型或自己写的循环生产级复杂业务比如客服、数据分析、多系统操作再考虑编排型。5.3 选型决策清单先问自己四个问题不要盲目追逐热门框架可以按下面的问题快速过滤我需要几个工具少于 5 个轻量方案足够超过 10 个编排型的工具调度能力更有优势。是否需要长期记忆和用户画像需要的话选自带向量记忆管理能力的框架。是否需要多 Agent 协作需要的话注意框架的通信机制是否成熟是否有良好的可观测性。团队里谁会维护这套系统如果是业务同学可视化工作流型更合适如果都是工程师任意类型都能驾驭。技术选型没有最优只有最匹配。我在不同项目里分别用过这四类至今没有一套框架走天下的冲动。6. 从能跑到跑好记忆增强、多智能体协作与评估6.1 给 Agent 加长期记忆从对话历史到向量检索最小实现里的 messages 列表就是最简单的短期记忆。需要增强长期记忆时我会引入向量检索把重要信息切片 → 嵌入为向量 → 存入向量数据库 → 在每轮开始前按相关性检索并注入上下文。伪代码思路如下from typing import List def build_query_memory(user_query: str, history: List[str], top_k: int 3): # 1. 对 user_query 做向量化得到 query_vector # 2. 在向量库中检索与 query_vector 最相似的 top_k 条记忆 # 3. 将检索结果拼入系统提示词 # 4. 同时把最近 3 条对话历史作为短期记忆放入 messages这里有三个工程要点切片要按语义不要机械按字数切。一段 300 字的技术结论切散了检索效果会很差。检索阈值要设置相似度低于阈值的记忆宁可不用也不要强行注入否则就是噪声。长期记忆要定时清理和去重否则向量库会越来越脏。6.2 多智能体协作分工、讨论与结果校验多智能体不是简单地把几个 Agent 串起来而是给它们明确的角色边界和通信协议。最常见的三种模式流水线模式A 做数据收集B 做数据分析C 生成报告。前一个的输出是后一个的输入。辩论模式两个 Agent 分别扮演方案提出者和方案评审者交替发言最后由裁判 Agent 收敛结论。层级模式主 Agent 负责任务拆解和结果汇总子 Agent 各自执行子任务向主 Agent 回报。我建议新手先做流水线模式因为它最容易理解和调优。辩论模式虽然效果上限高但很容易陷入无限辩论务必设置最大轮数。层级模式适合复杂的真实业务但主 Agent 的上下文压力会很大一般需要做中间结果压缩。6.3 定量评估一个 Agent 好不好用很多人评估 Agent 只看答得对不对这远远不够。我常用的指标如下指标计算方式说明任务完成率在一组测试任务中成功完成的比例最核心的战斗力指标工具调用准确率模型正确选择工具并生成合法参数的比例诊断模型对工具文档的理解程度无效步数平均每个任务中模型绕弯、重复、无效调用工具的次数反映规划质量Token 消耗平均每个任务的输入输出 token 总数直接影响成本端到端延迟从用户输入到最终回答的耗时决定用户体验我在上线任何 Agent 之前都会准备 20-50 条典型任务按上面的指标自动跑一遍评估流程再针对工具调用准确率低和无效步数多这两个问题做专项优化。没有评估体系的 Agent 项目后期优化基本靠拍脑袋。6.4 三个常见的进阶方向当你跑通基础版本后可以根据业务需求选一个方向深入浏览操作型 Agent让模型通过操作浏览器页面完成任务适合需要登录、点击、填表的场景。代码解释器型 Agent提供一个安全的 Python 执行环境让模型写代码、运行、分析结果适合数据处理和图表绘制。企业知识库型 Agent把内部文档存入向量库Agent 通过检索增强回答适合问答客服、员工助手。我个人的建议是先把基础知识库型 Agent 做扎实因为它技术难度适中、业务价值直接、踩坑成本低。代码解释器型 Agent 风险最高需要严格隔离环境但效果上限也最高。7. 实操中避开的那些坑上下文污染、死循环与工具幻觉7.1 上下文污染工具返回塞满上下文模型直接迷失这是我在调试 Agent 时遇到最多的问题。现象是Agent 前半段还很正常到了后半段开始重复问你想让我做什么或者干脆输出不相关的内容。排查一看往往是最开始某个工具返回了 1 万字的内容把模型的注意力全部吸走了。解决方法是分层控制上下文工具返回内容进上下文前强制截断单次不超过 1500 字符定期让模型对已有过程做摘要压缩用摘要替代原始长历史系统提示词中强调只关注与当前目标相关的工具结果。记住一个原则上下文不是越大越好而是越精越好。7.2 死循环与重试风暴模型反复调用同一个工具另一种高频问题是死循环。模型可能因为某个工具一直返回错误就一直用同样的参数重试同一工具直到轮次上限耗尽。这种重试风暴既消耗 token又让用户体验极差。我的应对策略有三层限制单工具最大调用次数比如同一工具最多连续调用 3 次超过后强迫模型换方案。让系统提示词明确写如果工具连续出错尝试修改参数或用其他工具而不是重复相同调用。在消息里增加历史尝试记录告诉模型哪些参数已经试过且失败了避免它重复。7.3 工具幻觉模型编造工具调用结果工具幻觉指的是模型没有真正调用工具却在答案里声称我已调用某工具并获得了结果。通常发生在模型上下文信息不足或者它认为猜一个结果比调用工具更省事的时候。要根治工具幻觉必须在架构上禁止口头调用。我的做法是要求模型每次调用工具都必须走结构化的 JSON 指令执行器会拿到 JSON 并真实执行在消息中明确标注凡是没有出现在观察结果里的信息你都不能声称来自工具。另外在最后输出时可以让模型核对一遍结论必须是基于实际观察结果的。7.4 成本失控与限流处理Agent 的成本比普通聊天接口高一个数量级因为一次任务可能有多次模型调用而且工具返回内容会增加输入 token。成本失控往往不是单次调用贵而是无效步骤太多。控制成本的方法对每个任务设置成本预算达到阈值后自动停止。动态模型切换简单任务用便宜小模型复杂任务才使用更强模型。使用缓存对相同的工具返回、相同的历史片段做命中缓存减少重复输入。设置并发限流与重试退避防止限流时高频重试导致雪崩。这点上我有过惨痛教训一个测试任务本来预估只要 2 万 token结果因为 6 次重复调用同一个失败工具最终消耗了 11 万 token。加入单工具次数限制后才真正解决问题。7.5 我的一点实操体会先小步验证再放权如果你只带走一句话我希望是这句Agent 的能力来自大模型但可靠性来自约束。我从第一次写 Agent 到现在最大的转变是心态不再追求让模型自由发挥而是想尽办法给它清晰的边界、合适的工具、可靠的护栏。每次增加一个新能力我都会先用一个最小用例验证再逐步扩大应用范围。尤其是涉及文件读写、外部 API、代码执行这些有副作用的操作必须默认先拒绝再按需放权。最后再分享一个很实用的小技巧写工具之前先花 15 分钟把工具描述写到尽善尽美。很多 Agent 表现不佳问题根本不在大模型而在工具描述太模糊。描述里要包含工具做什么、什么时候用、什么时候不要用、参数格式、返回结构、常见错误。好的工具描述可以说是整个 Agent 项目里性价比最高的投资。