ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent记忆与工具调用实战:从上下文窗口到MCP协议

Agent记忆与工具调用实战:从上下文窗口到MCP协议 上下文窗口又快满了而那把 800 行的代码库里 Agent 只看到了前 300 行。问它第一版方案怎么定的它支支吾吾开始胡编。以前我遇到这种事第一反应是换更大的上下文模型后来我发现真正的问题不是窗口不够大而是我压根没给 Agent 设计记忆系统和工具出口。这篇东西就是我在这大半年里把 Agent 从对话玩具改造成能干活的项目成员的完整记录主线就两条Agent 该怎么记住东西以及 Agent 该怎么调工具。而这两条线最后都汇到了同一个词上——MCP。1. 上下文窗口不是记忆先搞清楚 token 的本质1.1 窗口长度与 token 的物理限制很多人觉得上下文窗口就是 Agent 的内存条128K、200K 容量越大Agent 记得越多。技术上方向对但理解得过于粗糙。先说 token 是怎么消耗的。你发一句帮我看下这个项目结构看起来很短进到模型里会被拆成几十个 token。如果系统提示词写了 3000 字再加两轮对话历史、一个工具返回的大 JSON分分钟就是 8000 token 起步。200K 的窗口听着多换算成中文大概是 15 万到 25 万字可那是总预算不是可用预算——系统提示、few-shot 示例、临时塞进去的参考资料、每轮工具调用产生的输入输出全都要从这里面扣。更隐蔽的是 KV Cache 的显存消耗。窗口越长模型推理时维护的 Key-Value 缓存就越占显存这不只是成本问题还会让响应时间明显变长。实测下来同样一个任务用满 200K 窗口的请求比只塞 8K 上下文的请求慢 30% 到 50%费率也按 token 计价水涨船高。1.2 为什么硬塞上下文是个坏主意我见过很多开发者的第一反应是怕 Agent 忘就把所有历史记录、所有文档、所有工具输出全塞进去。这属于用战术上的勤奋掩盖战略上的懒惰。塞太多垃圾信息模型的长程注意力会退化。真实翻车场景是这样的我在一个晚点项目里把 30 天的对话记录全放进上下文结果 Agent 对第 2 天讨论的订单状态机核心结论回复得驴唇不对马嘴——它确实看到过但重要信息被淹没在海量无关内容里注意力被稀释了。行业里有篇研究论文结论是模型在长上下文中普遍存在Lost in the Middle现象即对中间位置的信息召回率明显低于开头和结尾。这不是个别模型的问题是当前架构的通病。所以我说上下文窗口不是记忆它更像一块随用随清的临时记事板。真正可靠的记忆机制得在窗口之外想方案。1.3 窗口用尽时的事故与应急方案上下文窗口不够用是每个 Agent 项目都会撞上的墙。表现形式分几种对话轮次一多早期关键约束被截断Agent 开始自由发挥。工具返回了上万行 JSON一次调用直接占掉半扇窗口。多文档比对任务塞两三个文件窗口就见底第四个挤不进来。应急手段我都试过列个表方便对照手段做法适用场景缺点粗暴截断只保留最近 N 轮对话短期闲聊类 demo丢失早期关键信息Agent 会出现失忆型幻觉摘要压缩把旧对话总结成 200 字摘要单轮长任务摘要本身就是有损压缩细节抗不过追问分块处理把任务拆成独立子任务各自开新会话批量处理类任务子任务之间状态无法共享需要外部状态管理降级检索先向量检索出相关片段再拼进上下文知识密集型任务检索质量决定了最后效果这些方案对应不同的场景但共同问题是都治标不治本。你压了旧对话新信息又会涌进来你分了任务块块和块之间的依赖就成了新难题。真正有用的思路是给 Agent 建立内存管理意识就像人写代码时会关掉不用的标签页、把重要笔记存到专门文件里Agent 也要有一套什么东西该留在窗口、什么东西该移出去的机制。这个机制就是后面要展开的 Agent 记忆体系。2. Agent 记忆体系的三个层次从短期缓冲到长期沉淀2.1 工作记忆上下文窗口的正确用法我给 Agent 设计的记忆体系分三层最底层是工作记忆承载在上下文窗口上。工作记忆的特点是容量小、速度快、随任务结束而清空。它的正确用法是放当前任务必须用到的信息而不是历史上所有可能有用的信息。实际操作中我会这样做系统提示词只保留角色定义、行为规范、核心流程总长控制在 1000 token 以内。任务相关的背景资料独立维护通过检索按需注入而不是常驻上下文。每轮工具调用结束后立刻对返回结果做摘要把大 JSON 压成字段数量、关键值、异常项几个要点。举个例子我做过一个数据库智能体需要让 Agent 综合多表数据回答业务问题。如果允许它直接把整个数据库导出的结果塞进上下文没跑几个问题窗口就爆了。后来改成它先通过工具拿表结构再根据任务生成 SQL 查询每次查询默认只取前 50 行做预览预览有问题再调整 SQL 拿全量数据。这样上下文里永远只留当前这一步的数据反而比硬塞更高效。2.2 情景记忆向量库与检索增强第二层是情景记忆对应的是这个 Agent 过去处理过什么事情、得出了什么结论、用户更偏好什么方案。这部分不能塞窗口里得放到外部存储需要的时候检索回来。最主流的实现是向量库。把历史对话、重要决策、用户偏好全部向量化存入数据库每次新任务启动前先做一轮检索把最相关的 N 条记忆拉回上下文。这本质上就是 RAG 的变体只不过检索的对象不是外部文档而是 Agent 自己的历史经验。选型上我踩过几个坑。初期用开源向量库起步数据量几千条没问题上到几万条后检索延迟明显增加而且没有过滤条件支持的话历史记忆里过时的结论也会被检索出来误导当前决策。后来我加了一层时间衰减权重不是所有历史都同等重要最近 7 天内的决策权重高超过 30 天的除非在长期总结里被确认否则默认降权。效果立竿见影——Agent 在新旧方案冲突时不再盲目听信旧经验了。长短期记忆网络那套思路其实对 Agent 记忆设计很有启发。人的记忆分感觉记忆、短期记忆、长期记忆三层每层的容量和保留时间不同。Agent 也一样窗口内的是短期缓冲向量库是长期仓库而中间的巩固机制——也就是定期把短期关键信息总结沉淀为长期记忆——是关键中的关键。没有这个巩固动作Agent 就永远是一次性的每次对话都得从零开始认识你。2.3 程序性记忆技能与工作流沉淀第三层是程序性记忆比情景记忆更高一层它记住的不是某件事的结果而是某类事该怎么做。用人类打比方情景记忆是你记得上次去这家餐厅点的红烧肉很好吃程序性记忆是你已经学会了做红烧肉的完整流程。在 Agent 架构里程序性记忆通常以技能和工作流的形式存在。现在很多 Agent 框架里都能看到技能文件其实就是一套结构化的指令加参数定义告诉 Agent遇到什么情况、按什么步骤、调用哪些工具。我自己最常用的一个技能是数据库模式识别当 Agent 接到的任务涉及新的数据库表时它会自动先查表结构、再查该表历史查询记录、然后生成并验证查询方案。这个流程固化成了技能文件后每次新任务都不用重新探索Agent 直接按标准流程走稳定性和效率都大幅提升。程序性记忆的积累是一个动态过程。我习惯每跑完一个复杂任务就复盘总结把这次哪几步是有效的、哪几步是绕了路的写成一个新的技能模板。这些模板会在之后的任务里反复被调用Agent 就越来越像一个熟手而不是每次都重新从零开始。有些框架里把这个过程叫记忆演化本质上就是让 Agent 的操作经验可积累、可复用、可升级。2.4 记忆持久化与跨实例迁移问题设计了三层记忆体系之后绕不开的问题是持久化和迁移。记忆存在哪怎么保证换台机器、换个对话环境记忆还在先说存储。工作记忆天然在会话里会话结束就没了情景记忆建议存向量库数据文件通常是 SQLite 或者独立的向量库文件可以跟随项目走程序性记忆以技能文件的形式存在项目目录里天然可以复制。关键是建立一个统一的序列化格式让三层记忆都能被导出和导入。我在实际项目里就做过一次记忆搬家。原本在电脑 A 上调试好的一套 Agent 记忆配置里面有几周积累的用户偏好和任务上下文要迁移到电脑 B 上。第一反应是直接把记忆库文件拷过去结果加载报错查了下是版本不一致导致 schema 不兼容。后来学乖了只在主版本一致的情况下平滑迁移而且所有记忆文件都放在统一目录用配置文件指定路径方便整目录复制。这就是为什么换账号/换机器延续 Agent 记忆这类需求如此普遍——所有人都希望自己在 A 环境积累的数字自我能无缝转移到 B 环境继续跑。这里给个实操建议从一开始就给你的记忆模块设计好导入导出接口通过工具函数序列化记忆数据这样后续无论是备份、迁移、还是跨环境部署都会轻松很多不用像我一样等出事了才补救。3. 工具调用的演进从硬编码函数到标准化协议3.1 函数调用的原生形态讲完记忆聊工具的出口。最初把工具能力开放给 Agent 的方式很原始你预先定义好多组函数每个函数有名字、参数、描述模型收到用户请求后如果判断需要某个工具就在回复里返回一个结构化的函数调用标记然后你的代码去执行这个调用再把结果回传给模型继续推理。这个流程业界叫 function calling 或者 tool use。用过一个理解媒介的比喻函数调用等于给了 Agent 一双手去操作外部世界。它不能凭空知道明天的天气但可以调用天气 API它不能手动打开网页但可以调用浏览器工具。这解决了模型只能思考、不能行动的根本短板。但用久了你会发现一个尴尬局面每个工具都要为特定模型做适配。一个 Agent 框架里定义了五六个工具换个模型有些模型支持函数调用有些不支持你得自己把调用结果解析成普通文本塞进去。工具一多代码库里堆满了一坨一坨的工具注册表和路由逻辑维护成本非常高。3.2 ReAct 循环中的工具选择工具调用真正发挥威力是在 ReAct 模式里。ReAct 的全称是 Reasoning Acting它的核心是一个循环Thought思考Agent 分析当前任务决定下一步做什么。Action行动如果是需要外部信息或外部操作的任务就调用某个工具并填好参数。Observation观察工具返回结果Agent 把结果作为新的上下文继续推理。循环以上步骤直到任务完成。我做过的一个文档整理 Agent 就用这个模式跑得很顺。给它一个压缩包它会先调用列举文件的工具看结构再调用读取工具看几个关键文件然后规划怎么整理之后一边重命名一边移动每一步都根据上一步结果调整策略。这就是 ReAct 的相对克制和可控。这个模式里有个关键点工具选择的质量直接影响整个链条的成败。模型怎么知道该调哪个工具靠的是工具描述。如果你把工具描述写得太笼统或太含糊Agent 就会先调错一个工具走回头路。比如说同样是获取用户信息这个需求。你如果把工具描述写为获取数据Agent 可能把它用来获取订单数据。正确写法是明确说明获取指定用户的账户信息包括昵称、邮箱、注册时间入参为 user_id。我在调这个环节上花了大量时间打磨工具描述和参数 schema绝对是值得的——工具描述质量提升后Agent 首轮工具调用准确率从六成直接拉到九成。3.3 工具描述的质量如何影响 Agent 表现工具描述不是给人看的是给模型看的。因此它的核心是指引模型在合适的时机正确填参、消除歧义并规避误用。我建议每个工具描述至少包含这些元素工具职责一句话说明说清楚干什么用、什么时候不用它。每个参数的语义、类型、是否必填、取值范围。一个典型调用示例尤其当参数含义容易混淆时。对常见错误的规避说明。比如输入日期格式为 YYYY-MM-DD不支持其他格式。另外工具的粒度也很讲究。太粗Agent 只能用几种固定操作灵活度差太细Agent 面对几十个同层级工具容易选错。我的一般标准是一套业务域内的小工具控制在 8 到 12 个之间每个工具做一件明确的事不在一个工具里堆多个功能分支。这样 Agent 的选择压力维持在舒服区。还有个容易忽略的点工具返回结果的格式对 ReAct 循环的影响。如果你的工具返回一个巨大的 JSON模型在下一步推理时往往会被无关字段干扰。我习惯在工具内部做一个精简层把原始数据过滤成摘要式答案只保留对后续决策有用的信息必要时再允许 Agent 发起二次查询拿细节。这才是把工具出口做得专业的方式——不只是接上外部世界还得让返回的信息易于消化。3.4 harness 与 agent 的边界谁在主控随着对 Agent 架构理解加深我发现很多关于工具调用的争论其实混淆了harness和agent的边界。Harness 指的是承载和调度 Agent 的外层框架负责环境初始化、记忆读入、工具注册、结果路由、安全策略。Agent 本身是那个思考决策的循环。工具既是 harness 里的资源也是 Agent 的行动空间。它们的关系有点像操作系统和应用程序harness 提供进程环境拿出接口能力agent 在上面跑业务流程决定如何调用可用能力。设计一个多工具 Agent 时这个边界不清会导致灾难。我在早期一版项目里把大量工具逻辑直接写进 Agent 提示词让 Agent自己决定怎么实现工具逻辑结果上下文迅速爆掉且逻辑混乱得根本无法调试。后来把所有工具、技能模板、请求上下文全部下沉到 harness 层Agent 只负责决策复用性和可维护性都大幅提升。4. MCP 协议Agent 的工具即插即用4.1 MCP 的定位与架构Host、Client、Server工具调用发展到最后阶段标准化是必然的方向。MCPModel Context Protocol就是在这个背景下出现的。简单说MCP 是一套开放协议定义了 AI Agent或叫 Host如何发现、调用外部工具和数据源。MCP 把架构拆成三个角色MCP Host承载 Agent 运行的主体比如 Claude Desktop、各类 IDE 插件、Agent 框架。Host 负责管理 MCP Client。MCP Client与 Server 建立连接、发送工具列表请求、发起调用同时云端计算工具结果要如何传回模型上下文。MCP Server暴露工具和数据资源的一端。任何本地程序或远程服务只要实现了 MCP Server 协议就能把自己的能力开放给任意支持 MCP 的 Host。对我来说 MCP 意味着两件事一是生态打通之前为特定 Agent 框架写的工具适配器现在只要实现 MCP Server就能被各种 Host 直接使用二是工具接入门槛从写代码适配降到配置文件注册这让非程序员也能给 Agent 接入工具。4.2 一个 MCP Server 的解剖空谈协议不如动手写一个。下面是一个最简单的 MCP Server 示例实现一个获取本地天气的工具用 TypeScript 的 SDK 写import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; const server new McpServer({ name: weather-server, version: 1.0.0, }); server.tool( get_weather, { city: { type: string, description: 城市名称如北京、上海 }, }, async ({ city }) { const data await fetchWeather(city); return { content: [{ type: text, text: ${city}当前天气${data.condition}气温${data.temp}℃ }] }; } ); const transport new StdioServerTransport(); await server.connect(transport);编译这个文件后在 MCP 配置文件里做一行注册{ mcpServers: { weather: { command: node, args: [/path/to/weather-server.js] } } }之后任意支持 MCP 的 Host 就能通过配置直接获取 get_weather 工具。整个过程不需要 Host 端写任何业务代码注册即用。这就是我理解的工具民主化——工具能力与 Agent 框架解耦了。我实际项目里测试时发现一个细节用 stdio 传输时Server 进程是随 Host 启动的日志输出一定要走 stderr 或单独日志文件不要 console.log 到 stdout否则会和协议通信数据混在一起导致 Host 解析失败。4.3 工具生态的扩展从开发工具到设计软件MCP 的生态扩展比我预期快得多。现在入手特别多的方向包括开发工具类数据库客户端、调试器、性能分析工具的 MCP Server 陆续出现Agent 可以直接查询表结构、执行 SQL、甚至操作断点。设计软件类有支持接入 Figma 等设计工具的 MCP 插件Agent 能读取画布元素、检查设计规范、直接修改图层属性。游戏引擎类像 Unreal Engine 5.8 的 MCP 插件Agent 可以在引擎里查询场景对象、打命令、修改属性。PCB 设计类Altium Designer 的 MCP 接口也在推进硬件工程师可以用 Agent 辅助布局检查和原理图分析。逆向工程类调试器如 x32dbg/IDA的 MCP 插件正在把让 AI 协助逆向分析从幻想变为可能。这些应用的共同点是一个相对封闭的专业软件开放成一个 MCP Server 后Agent 就能在专业领域发挥真正的生产力价值。我自己的体会是越封闭的工具MCP 的价值越大——它像是给AI 员工配上了各种专业设备的操作权限。MCP 是什么这个问题现实中很快就变成了你的 MCP 还能接什么。4.4 授权、鉴权与流式输出的现实问题MCP 好归好现实接入中有几个坎必须说清楚。第一个坎是授权。很多 SaaS 工具的 MCP Server 需要 OAuth 授权比如接入 Notion、Figma 时用户需要在浏览器里完成授权流程。问题在于流程设计不同有些是把授权页 URL 打印在终端你得手动复制打开再粘贴回调码有些则要求提前在云控制台里建好应用凭据。我见过最多翻车的是回调地址不一致——本地跑的是http://localhost:3000/callback云端的回调只能配一个固定地址两边对不上就无限转圈。解决方案是严格按官方文档配好重定向 URI且不要自定义改动默认端口。第二个坎是鉴权信息的存储。MCP 配置里直接写明文 token 是常态但这有泄露风险。比较稳妥的做法是让 Host 从系统密钥库读取这类密钥或者至少在配置文件里引用环境变量避免把敏感信息直接写死在明文配置里。第三个坎是流式输出。有些 Agent 框架调用工具时默认一次性收集全部结果再返回如果工具本身是流式的比如日志实时输出、长任务进度上报Agent 就会被卡在等待状态用户感觉他假死。要解决这个问题需要 Host 端支持流式接收工具结果并把增量逐步注入上下文。这个和大模型上下文窗口用完了怎么办又关联起来了——流式注入如果控制不好窗口压力会陡增。我目前的做法是给流式工具设置输出上限默认最多保留最近 N 行超出部分折叠成一个摘要条目。这儿有另一个容易被忽略的坑工具调用超时的处理。MCP 默认的超时设置往往较短而一些真实工具比如批量文件处理、大型分析任务可能需要几分钟。超时后 Host 会认为工具失败Agent 可能误判之前的操作没有生效然后重复执行导致负作用。建议在 MCP Server 内部自己实现长任务的状态查询机制让 Agent 能通过另一个工具查询任务进度而不是长时间阻塞在同一次调用里。5. 记忆与工具的协同如何设计一个靠谱的 Agent5.1 记忆决定工具选择的结构化流程前两章讲了记忆和工具实际上这两者在真实 Agent 运行中是交织在一起的。设计得好的 Agent会先用记忆辅助决策再通过工具执行短期结果又会沉淀回记忆形成飞轮效应。我设计过一套可复用的流程五步走上下文加载任务进来先检索情景记忆找到与此前相似任务相关的经验总结。技能匹配根据任务类型匹配技能模板确定执行路径。工具申报按技能模板列出可用工具集合不把所有工具全开放给 Agent全开放会让选择压力太大。执行循环ReAct 循环内逐步调用工具每步的结果经精简后写回工作记忆。记忆巩固任务结束后由 Agent 或后处理脚本总结关键经验和结论写入长期记忆。这五步的关键在于记忆在前、工具在后。没有记忆做引导Agent 面对几十个工具就像新手进厨房——每种调料都用菜却做得稀烂有了记忆做前导它很快就能找到最趁手的工具和操作方式变得越来越熟练。5.2 上下文管理的实操策略上下文管理是整套架构的命脉策略不对再多记忆和工具都白搭。我沉淀了三个核心习惯第一是上下文降噪。凡是已经固化为程序性记忆的流程就不需要留大段解释文字在上下文里系统提示词只用一句遇到 XX 情况按 XX 技能处理。这样省出的空间去容纳工具返回的更精确信息。第二是工具结果二次压缩。前面说过工具返回的结果要先过一道精简层。具体操作上我写过一个通用的 summarize_tool_result 工具任何工具返回超过 500 token 的内容都会被它压缩成核心要点。这样即使工具输出一万行Agent 上下文里也只多几百 token。第三是分层上下文归档。当上下文使用率超过 70% 时触发归档机制把早期对话切成几段逐段总结把已完成的决策节点合并成摘要条塞回记忆库。这个机制很像人类的备忘录习惯——不是事无巨细地记而是把重要事态保存下来、把过程留空到处翻找详细就无法聚焦了。5.3 渐进式压缩与摘要级联的经验具体实施里摘要压缩是有层级的不能一股脑全压缩。我用的模式叫摘要级联三层往下走第一层单轮对话摘要。每轮任务完成后立即做保留关键结论和决策理由。第二层工作会话摘要。一个长会话进行到一半把已完成的小节压缩合并。第三层跨会话长期记忆。当一个项目阶段结束把所有关键经验合并成项目笔记存入向量库。逐级存储的好处是每一层摘要都有明确的粒度定位不会被揉成一团。Agent 处在某个具体任务中间时读的是第一层或第二层信息处理跨天连续任务时读第三层。这样信息的粒度和时效性都能保住。顺便提一下 building 一个 Agent 框架的路径选择。我用过 Python 也试过 Rust。Python 生态成熟快速迭代方便但如果你的 Agent 会长期运行、并发调工具、需要高性能的本地记忆处理Rust 的可靠性和资源占用会更适合。有位同行用一个基于 Rust 的 Agent 框架做本地知识库管理启动速度比 Python 版本快约 3 倍内存占用降了一半处理上千个文件的任务明显更稳。不过这属于工程实现层的权衡不影响前面讲的架构思路。6. 实测中的坎与解法调试 MCP、迁移记忆、避免幻觉6.1 MCP 连接失败的完整排查链路MCP 接入不出问题是不可能的出问题最好别慌按链路排查。我遇到过几次总结出典型的排查顺序第一步确认 Server 进程有没有起来。用 stdio 模式的 MCP ServerHost 启动时会拉起子进程如果 launch 失败客户端会直接报错。检查点包括路径是否写错、node/python 是否在 PATH 里、依赖是否装全。这步最容易被忽视的是当前目录——MCP Server 启动的 cwd 通常跟配置文件所在目录有关如果 Server 读取相对路径的资源cwd 错了就白启动。第二步确认协议通信是否正常。如果 Server 能启动但工具列表为空大概率是协议握手出问题。用 MCP Inspector官方的调试界面手动连接同一个 Server看能不能列出工具、能不能成功调用单个工具。如果 Inspector 里能通、Host 里不能问题大概率出在 Host 的配置或权限层。第三步排查授权和鉴权。走 OAuth 的 MCP Server先检查 token 是否还有效、回调地址是否匹配。我见过一个很隐蔽的问题Host 和 Server 在本地通信走的是 localhost但某些云端工具的授权回调硬编码为 http://127.0.0.1 而不是 http://localhost导致回调永远匹配不上。解决方法是统一把 localhost 改成 127.0.0.1 或反过来保持一致再试。第四步看报错日志。MCP 报错信息有时候很开放只说tool call failed。这时第一件事是看 Host 侧日志、Server 侧 stderr哪个都不看就只能瞎猜。我在本地一直开着 Server 的各种日志输出到独立日志文件里出问题先 grep 日志。6.2 记忆模型的跨端配置同步基架搭好后记忆的跨端问题来了。最早的项目里记忆是本地文件用户换台电脑就全丢了。后来我给记忆模块加了独立目录它的核心是一套可变的数据结构包含了用户偏好、任务历史、技能定义。有了统一目录和统一 schema备份、迁移就能实现。操作上我这样干的记忆目录里放三个文件profile 存用户偏好history 存情景记忆的索引向量库本体在 data 子目录skills 存技能模板。sync 的时候先跑一次记忆导出把 profile、技能、关键记忆向量全部导出为 JSON再在目标环境执行记忆导入。有版本差异的话在导入前先做一轮数据形态兼容性检查。有人问怎么保证迁移过去之后 Agent 还记得之前的上下关系我的回答是迁移的只是一部分底层信息Agent 自己的模型权重不会变迁移后记忆和能力的结合在新环境重新推理只需重启时自动检索一遍核心记忆把结论直接加载进系统提示词即可。这和换账号延续记忆的大逻辑一致——账号是个身份边界记忆要跟着身份走不是跟着设备走。6.3 Agent 的安全边界与权限收缩最后再聊安全Agent 一旦接入工具手能碰到了真实世界权限控制就必须认真对待。我在设计 Agent 的工具安全策略时一直践行最小权限原则具体操作有三条默认禁用有副作用的高风险工具删除文件、执行 SQL 修改类操作、发送请求、转移资源的所有权需要用的时候一次性授权。所有工具调用都要留痕能追溯哪一步调了哪个工具、传了什么参数、改了什么内容。禁止 Agent 读取密钥类敏感信息即使模型目的是善意的数据泄露风险也不可忽略。有一回我做一个文件管理 Agent它需要按规则重命名并移动一批文件。测试时发现 Agent 把文件移动到了错误目录原因是它看错了参数语义——把目标目录和源目录填反了。如果这发生在生产环境几十个文件的位置就乱了。这就是为什么工具描述和参数校验要放到同等重要的位置。加一道参数校验层对高危参数做白名单校验Agent 再聪明也不能胡来。还有一个容易被忽略的点Agent 在多次工具调用的循环里也可能产生代理幻觉它可能认为某一步操作成功了实际上那一步被权限拦截了但错误信息不够显眼。解决方法是让所有被拦截的操作返回结构化了的结果包括操作被安全策略拒绝及具体背后的原因这样 Agent 能基于真实状态调整计划而不是以为一切正常。把记忆和工具这两件最核心的事想清楚Agent 的质量会有一个明显的跃迁。我自己的感想是模型本身的强弱只是底线记忆设计决定 Agent 能否真正积累经验MCP 这类标准协议则决定了它能触达多宽的世界。最后分享一个我一直在用的小技巧给 Agent 的每次投产都留记忆版本也就是完成重大迭代一周后再回到对话里问它当初的方案、思路和当时踩的坑如果答得清晰说明记忆链路健康如果含糊、甚至开始编了那说明上下文管理和记忆回收的地方还有漏洞值得回去再调。这套回访法则比任何测试用例都更能暴露一个 Agent 的真实记忆能力。
返回列表