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。重点是两步:
- 把一次交互里的有效经验提纯出来。
- 把这些经验重新作用到下一次决策里。
如果只做第一步,那叫“会记事”。
两步都做了,才叫“会成长”。
记忆层不是聊天存档,它更像值班日志
上一篇我们讲记忆层时,重点在“跨会话记住用户事实”。这一步当然重要,但还只是地基。
真正好用的记忆层,更像团队里的值班日志。它不只是记“今天发生了什么”,还会记三类对下次有用的东西:
- 用户事实:技术栈、偏好、禁忌、历史问题
- 行为经验:这次回答哪里答偏了,哪里答对了
- 策略结果:哪个 Prompt 更稳,哪个工具更靠谱
这样一来,记忆层就不再是一个聊天归档盒,而是一块持续更新的经验面板。
这一层一旦搭好,进化就不再神秘。它其实就是一个很朴素的闭环:
- 先交互
- 再复盘
- 把复盘写进记忆
- 下次决策前把记忆拿出来用
现在很多主流 Agent 框架里,名字虽然各不相同,但最后都绕不过这个闭环。
主流 Agent Skills,最后都会落到这三类
你去看现在常见的 Agent 系统,不管它叫 Skill、Tool Strategy、Critic、Policy Update 还是 Self-Reflection,本质上大多能归到三类:
- 反思:判断这次做得怎么样
- Prompt 自优化:把经验写回行为规则
- 工具学习:记住哪个工具在什么场景下更好用
这三类之所以值得先做,不是因为它们最炫,而是因为它们最容易落地,而且确实能让 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 串起来,最小闭环其实不复杂:
- 回答前,先取用户事实和历史经验
- 回答后,生成一条反思
- 反思积累到一定数量,更新一次系统 Prompt
- 工具调用结束后,把成败写进记忆
下面给一个可以直接看懂主流程的整合版本:
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 上先做一件最有收益的事,我建议顺序是:
- 先上反思 Skill
- 再接 Prompt 自优化
- 最后补工具学习
把这三步接通,你的 Agent 才会从“记得你说过什么”,慢慢变成“知道下次该怎么做”。
系列串联:本文承接上一篇《给 Agent 装一个真正能用的记忆层》。如果你还没搭好记忆层,建议先看上一篇,再回来补这一篇。
如果你在做代码 Agent、客服 Agent 或运维 Agent,这套结构都能直接套。差别不在框架,在你肯不肯把经验真正写回系统。
