当前位置: 首页 > news >正文

3 个 Skills + 1 个记忆层,打造能成长的 Agent

摘要:很多人给 Agent 加了记忆层,以为它就会越来越聪明。结果用了一个月,还是老样子。原因不在模型,而在系统设计。记忆如果只负责“存”,Agent 就只是在反复翻旧聊天记录;记忆如果能接住复盘、改写 Prompt、记录工具成败,它才会开始积累经验。本文承接上一篇记忆层文章,用 3 个最常见也最值得先上的 Agent Skills,搭一套真正会“越用越顺手”的进化闭环。

文章标签:#Agent自进化 #AgentSkills #记忆层 #Reflection #Prompt优化 #ToolUse
预计阅读时间:11 分钟

目录

  • 为什么很多 Agent 用久了,还是像新来的
  • 记忆层不是聊天存档,它更像值班日志
  • 主流 Agent Skills,最后都会落到这三类
  • Skill 1:反思,让一次对话变成一条经验
  • Skill 2:Prompt 自优化,把经验写回系统提示
  • Skill 3:工具学习,给工具调用建立胜负账本
  • 一张最小可跑的进化 Agent 架构
  • 工程落地时最容易踩的 4 个坑

为什么很多 Agent 用久了,还是像新来的

一个代码审查 Agent,第一次看你的仓库,批评得很认真:

  • 变量名不够长
  • 注释太少
  • 风格不统一

你告诉它:“我们团队就用短变量名,注释只写复杂逻辑,别按教科书那套来。”

第二天再开一个新会话,它还是老一套。

这类 Agent 最大的问题,不是它记不住,而是它不会把记住的东西写回自己的做事方式。它像一个每天下班都不写交接日志的新同事。你昨天刚说过的话,今天它又得重来一遍。

所以,“Agent 自进化”这件事,重点从来不是把上下文窗口继续做大,也不是把更多聊天记录塞进 Prompt。重点是两步:

  1. 把一次交互里的有效经验提纯出来。
  2. 把这些经验重新作用到下一次决策里。

如果只做第一步,那叫“会记事”。

两步都做了,才叫“会成长”。

记忆层不是聊天存档,它更像值班日志

上一篇我们讲记忆层时,重点在“跨会话记住用户事实”。这一步当然重要,但还只是地基。

真正好用的记忆层,更像团队里的值班日志。它不只是记“今天发生了什么”,还会记三类对下次有用的东西:

  • 用户事实:技术栈、偏好、禁忌、历史问题
  • 行为经验:这次回答哪里答偏了,哪里答对了
  • 策略结果:哪个 Prompt 更稳,哪个工具更靠谱

这样一来,记忆层就不再是一个聊天归档盒,而是一块持续更新的经验面板。

这一层一旦搭好,进化就不再神秘。它其实就是一个很朴素的闭环:

  • 先交互
  • 再复盘
  • 把复盘写进记忆
  • 下次决策前把记忆拿出来用

现在很多主流 Agent 框架里,名字虽然各不相同,但最后都绕不过这个闭环。

主流 Agent Skills,最后都会落到这三类

你去看现在常见的 Agent 系统,不管它叫 Skill、Tool Strategy、Critic、Policy Update 还是 Self-Reflection,本质上大多能归到三类:

  1. 反思:判断这次做得怎么样
  2. Prompt 自优化:把经验写回行为规则
  3. 工具学习:记住哪个工具在什么场景下更好用

这三类之所以值得先做,不是因为它们最炫,而是因为它们最容易落地,而且确实能让 Agent 变顺手。

下面直接上工程做法。

Skill 1:反思,让一次对话变成一条经验

很多团队做 Agent,喜欢把所有精力都放在“回答时怎么推理”。其实真正容易被忽略的,是“回答完之后怎么复盘”。

反思 Skill 的任务很单纯:在每轮对话结束后,用一个便宜模型写一条短复盘。别写成长文,够用就行。目标不是感动自己,是为了给下一轮决策提供素材。

这里有个原则很好用:反思不求全面,只求可执行。

与其存一大段抽象点评,不如存三条具体结论:

  • 这次做对了什么
  • 这次做错了什么
  • 下次遇到类似问题先检查什么
importjsonfromdatetimeimportdatetimefromtypingimportAnyfromdotenvimportload_dotenvfrommem0importMemoryfromopenaiimportOpenAI load_dotenv()memory=Memory()llm=OpenAI()defcall_json(prompt:str)->dict[str,Any]:response=llm.chat.completions.create(model="gpt-4o-mini",temperature=0.2,response_format={"type":"json_object"},messages=[{"role":"user","content":prompt}],)returnjson.loads(response.choices[0].message.content)defreflect_on_conversation(messages:list[dict[str,str]],user_id:str)->dict[str,Any]:compact_history="\n".join(f"{m['role']}:{m['content']}"forminmessages[-6:])prompt=f""" 请复盘下面这段对话,并只输出 JSON。 目标: 1. 找出这次回答中做对的 1-2 点 2. 找出最该修正的 1-2 点 3. 给出下次处理同类问题时的具体动作 对话:{compact_history}输出格式: {{ "summary": "一句话总结", "good": ["..."], "bad": ["..."], "next_actions": ["..."] }} """.strip()reflection=call_json(prompt)timestamp=datetime.now().isoformat(timespec="seconds")memory.add((f"反思记录\n"f"总结:{reflection['summary']}\n"f"做对:{';'.join(reflection['good'])}\n"f"做错:{';'.join(reflection['bad'])}\n"f"下次先做:{';'.join(reflection['next_actions'])}"),user_id=user_id,metadata={"type":"reflection","created_at":timestamp},)returnreflection

比如用户已经说过“代码风格以团队约定为准”,但 Agent 还是按通用规范长篇输出。一次好的反思记录,大概会长这样:

总结:回答方向基本正确,但忽略了团队既有规范。 做对:先指出了可读性问题;给了修改建议。 做错:重复批评了用户已明确接受的短变量名风格。 下次先做:先检索历史偏好;命中团队规范后再决定是否展开风格建议。

你会发现,这就已经不是聊天记录了。这是一条经验。

Skill 2:Prompt 自优化,把经验写回系统提示

只有反思,没有改动,Agent 顶多算“会认错”。它还没有进化。

第二个 Skill 的作用,是把最近几次反思里重复出现的问题,重新写回系统 Prompt。你可以把它理解成给 Agent 改 SOP。

这个动作不需要每轮都做。实际工程里,按批次触发更稳:

  • 每 5 次对话更新一次
  • 或者每天低峰期批量更新一次
  • 或者只有用户明确点踩时才触发

下面这个实现比较稳妥。它不直接依赖后端的 metadata 精确过滤,而是先召回,再在应用层筛选,兼容性更好。

fromhashlibimportsha1defget_memories_by_type(query:str,user_id:str,memory_type:str,limit:int=8)->list[dict[str,Any]]:results=memory.search(query=query,user_id=user_id)matched=[]foriteminresults:metadata=item.get("metadata")or{}ifmetadata.get("type")==memory_type:matched.append(item)returnmatched[:limit]defoptimize_system_prompt(current_prompt:str,user_id:str)->str:reflections=get_memories_by_type(query="反思记录 回答偏差 用户偏好 工具选择",user_id=user_id,memory_type="reflection",limit=8,)ifnotreflections:returncurrent_prompt notes="\n".join(f"-{item['memory']}"foriteminreflections)prompt=f""" 你是资深 Prompt 编辑。请根据下面的反思记录,改写当前系统 Prompt。 要求: 1. 保留原任务边界 2. 只增强稳定性,不改变产品定位 3. 优先吸收高频失误对应的修正规则 4. 直接输出完整 Prompt,不要解释 当前 Prompt:{current_prompt}反思记录:{notes}""".strip()new_prompt=llm.chat.completions.create(model="gpt-4o-mini",temperature=0.2,messages=[{"role":"user","content":prompt}],).choices[0].message.content.strip()old_version=sha1(current_prompt.encode("utf-8")).hexdigest()[:8]new_version=sha1(new_prompt.encode("utf-8")).hexdigest()[:8]memory.add((f"Prompt 更新\n"f"旧版本:{old_version}\n"f"新版本:{new_version}\n"f"变更原因:最近反思里多次出现同类失误"),user_id=user_id,metadata={"type":"prompt_update","created_at":datetime.now().isoformat(timespec="seconds")},)returnnew_prompt

这一步一旦跑起来,Agent 的系统提示就不再是写死的初始化文本,而是会慢慢吸收真实使用中的摩擦。

这也是为什么很多人觉得“我明明加了记忆,Agent 还是不长进”。因为它只把记忆拿来补充上下文,没有拿来改行为规则。

Skill 3:工具学习,给工具调用建立胜负账本

第三个 Skill 常常最容易见效。

因为很多 Agent 的真实问题,不是不会说,而是不会选工具。比如:

  • 查文档时总爱先走慢接口
  • 抓网页时明明该用结构化 API,却先上浏览器
  • 一个工具已经连续超时三次,下次还继续试

这时候最值钱的,不是让模型“更聪明一点”,而是先把工具成败记账。

defrecord_tool_result(tool_name:str,task:str,success:bool,note:str,user_id:str)->None:outcome="成功"ifsuccesselse"失败"memory.add(f"工具记录\n任务:{task}\n工具:{tool_name}\n结果:{outcome}\n备注:{note}",user_id=user_id,metadata={"type":"tool_result","tool_name":tool_name,"success":success,"created_at":datetime.now().isoformat(timespec="seconds"),},)defchoose_tool(task:str,candidates:list[str],user_id:str)->str:records=get_memories_by_type(query=f"{task}工具记录 成功 失败",user_id=user_id,memory_type="tool_result",limit=12,)ifnotrecords:returncandidates[0]history="\n".join(f"-{item['memory']}"foriteminrecords)prompt=f""" 请为当前任务选择一个最合适的工具。 任务:{task}候选工具:{candidates}历史记录:{history}规则: 1. 优先选择同类任务中成功率更高的工具 2. 连续失败的工具降权 3. 只输出一个工具名 """.strip()answer=llm.chat.completions.create(model="gpt-4o-mini",temperature=0.1,messages=[{"role":"user","content":prompt}],).choices[0].message.content.strip()returnanswerifanswerincandidateselsecandidates[0]

比如天气查询工具tool_a连续超时两次,tool_b虽然慢一点但稳定。只要你把这件事写进记忆,Agent 下一次就不至于继续撞墙。

这类 Skill 很像给团队做值班手册。哪个工具在什么场景下靠谱,别靠口口相传,直接记账。

一张最小可跑的进化 Agent 架构

把前面三个 Skills 串起来,最小闭环其实不复杂:

  1. 回答前,先取用户事实和历史经验
  2. 回答后,生成一条反思
  3. 反思积累到一定数量,更新一次系统 Prompt
  4. 工具调用结束后,把成败写进记忆

下面给一个可以直接看懂主流程的整合版本:

classEvolvingAgent:def__init__(self,user_id:str,system_prompt:str)->None:self.user_id=user_id self.system_prompt=system_prompt self.turn_count=0self.history:list[dict[str,str]]=[]defrecall_context(self,query:str)->str:memories=memory.search(query=query,user_id=self.user_id)ifnotmemories:return"无相关历史。"return"\n".join(f"-{item['memory']}"foriteminmemories[:6])defchat(self,user_query:str)->str:context=self.recall_context(user_query)final_prompt=f"""{self.system_prompt}已知历史:{context}用户当前问题:{user_query}""".strip()response=llm.chat.completions.create(model="gpt-4o-mini",temperature=0.3,messages=[{"role":"user","content":final_prompt}],)answer=response.choices[0].message.content.strip()self.history.extend([{"role":"user","content":user_query},{"role":"assistant","content":answer},])self.turn_count+=1memory.add(messages=self.history[-2:],user_id=self.user_id)reflect_on_conversation(self.history[-6:],user_id=self.user_id)ifself.turn_count%5==0:self.system_prompt=optimize_system_prompt(self.system_prompt,self.user_id)returnanswer

这个版本当然还很简化,但已经够你把整套机制跑起来。后面要扩展,也基本是沿着这三条线继续长:

  • 反思更细
  • Prompt 更新更稳
  • 工具选择更准

工程落地时最容易踩的 4 个坑

1. 反思写太长,最后没人用

复盘不是周报。你真正要的,是一条下次还能触发的经验,而不是一篇情真意切的自我检讨。控制在一句总结加两三条动作,最实用。

2. Prompt 改得太勤,系统会飘

很多团队一看到“自动优化”,第一反应就是每轮都改。这样很容易把 Agent 改成另一个东西。比较稳的做法是批量更新、保留版本、随时可回滚。

3. 记忆越来越肥,检索越来越虚

经验不是越多越好,旧经验还可能误导新决策。实战里建议给反思和工具记录加 TTL,只保留最近 30 天或最近 N 次高价值记录。

4. 把“自进化”理解成“无人监管”

自进化不等于放飞。尤其是 Prompt 更新和工具策略调整,最好留一个人工审核开关,至少在早期阶段别让它完全自改。

最后

Agent 自进化这件事,说穿了不玄。

它不是某个神秘新模型,也不是再叠一层宏大框架。多数时候,它就是把“这次做得怎么样”“下次该怎么做”“哪个工具别再用了”这三件事,认真记下来,再真的用回去。

所以如果你准备在现有 Agent 上先做一件最有收益的事,我建议顺序是:

  1. 先上反思 Skill
  2. 再接 Prompt 自优化
  3. 最后补工具学习

把这三步接通,你的 Agent 才会从“记得你说过什么”,慢慢变成“知道下次该怎么做”。


系列串联:本文承接上一篇《给 Agent 装一个真正能用的记忆层》。如果你还没搭好记忆层,建议先看上一篇,再回来补这一篇。

如果你在做代码 Agent、客服 Agent 或运维 Agent,这套结构都能直接套。差别不在框架,在你肯不肯把经验真正写回系统。

http://www.jsqmd.com/news/1125780/

相关文章:

  • 人工智能模型部署与推理服务性能调优
  • 如何建立自己的“表达结构库”
  • 深度解析 | RevokeMsgPatcher如何用二进制魔法让撤回消息“无处可藏“
  • JAVA 代码赏析:优雅的 Token 提取策略
  • SpringBoot 整合 XXL-JOB——分布式任务调度实战
  • 大气层1.7.1整合包:Switch破解系统的终极完整配置指南
  • IntelliJ IDEA 创建 Maven 项目完整指南
  • PySpark Join性能优化:解决Shuffle倾斜与Python序列化瓶颈
  • AI学习(2)——补:linux自启动llama
  • 南京会场 | 7-8月学术会议征稿通知
  • 开发板驱动环境配置(ROCK 5C为例)
  • 当我们在谈论“开源低科技”时,我们在谈论什么?
  • 数据库学习笔记2——MySQL 的锁机制
  • 编译原理第三版第五章课后题1-2题
  • 本地代码编辑器集成DeepSeek模型:从原理到实践的完整指南
  • 【计算机毕业设计】基于Java的智能停车场预约收费系统
  • Plone开发环境搭建:pip install的正确用法与边界
  • 自定义AES变形加密
  • 2026年标书制作公司专业度大比拼,哪家能脱颖而出?
  • 炉石传说脚本Hearthstone-Script:5分钟实现智能自动化对战的终极指南
  • 硅胶密封件实测:2026年7月亲测排行
  • 局域网文件共享实战:从“账户被禁用”到成功互传文件
  • Dify工作流与MCP服务:构建可嵌入IDE的AI智能副驾
  • DMDUL:达梦数据库离线抽取数据工具
  • 告别西门子依赖!C# 实现信捷 XD 系列 PLC 通信与数据采集
  • 普通人别死磕芯片级维修!设备装调,才是普通人更稳的技术出路
  • WP7有约(二):课后作业
  • Window系统Claude Code安装教程
  • 自动售货机的商品供应链管理,怎么做更高效~YH
  • 我用 Codex 复刻了一个 Windows 11 计算器,过程比想象中真实多了