简介:Hermes Agent 是 Nous Research 团队开源的自我进化型AI智能体框架,面向AI开发者、大模型学习者和需自动化处理任务的独立开发者,支持Linux、macOS和WSL2等环境,低配置服务器也能流畅运行;核心价值在于通过 MEMORY.md 持久记忆与自动技能沉淀,让智能体跨会话不丢上下文,越用越顺手。源码约含2000个文件,以Python脚本(820个py)、Markdown说明(1036个md)和YAML配置(95个yaml)为主,另有少量JSON、Shell脚本与前端样式文件,整个压缩包仅54.02MB,便于本地部署和二次修改。目前已有69人学习浏览。读者可拿到完整可运行的工程源码、一键环境安装脚本、跨平台部署配置及项目文档,既能直接搭建个人AI助手处理对话任务,也能深入理解智能体记忆管理、技能复用和工具调用的具体实现;项目基于MIT协议开源,适合学习交流与非商业二次开发。
1. 为什么「自我进化」四个字值得你先别急着质疑
第一次看到「Hermes Agent-main 自我进化型AI智能体框架源码」这个标题,多数人的第一反应是:自我进化是不是营销话术?我在本地把源码跑起来之前也是这么想的,直到我亲眼看到同一个 agent 在连续跑完三轮同类任务后,第二轮不再犯第一轮的错,第三轮直接复用前两轮沉淀下来的工具调用序列,才意识到这个「进化」不是玄学,而是记忆、反思和技能库三件事被工程化地咬合在了一起。这篇笔记面向的是想自己动手复现、想把这套机制搬进自己业务里的开发者,我会从框架的最小运行讲起,再讲清楚进化的触发条件和参数边界,最后给出验证它是否真在进化的方法。
2. 自我进化型智能体的底座:记忆、反思与技能库是怎么咬合的
2.1 先看整体架构:进化的三个前提组件
常见做法里,「自我进化」的agent不是靠某个神奇的算法单点突破,而是靠三层结构协同。最底层是记忆系统,负责把每次任务的过程、结论、失败原因持久化;中间层是反思引擎,在任务结束后对刚发生的过程做复盘并产出可执行的改进建议;最上层是技能库,把改进建议落地成新的工具、提示词模板或调用策略。Hermes Agent-main 这套源码走的正是这个路线,它的目录里基本可以找到memory、reflection、skills三个核心模块,分别对应上述三层。
我一般会把这三层的关系理解成一个循环:任务执行 → 经验沉淀 → 反思产出改进项 → 技能库更新 → 下一次任务带着新技能执行。只要这个循环在跑,就谈不上「进化」,因为经验没有回流到下一次决策里。所以拿到源码后第一步不是看模型怎么调,而是先确认这个循环的入口和出口在哪里。
这个循环里的关键设计是「什么算经验」。不是所有对话历史都是经验,只有经过反思引擎筛选、并且能被技能库执行的那部分才算。源码里通常会有一个post_task_reflection类的入口,它会在任务结束后被调用,把执行日志压缩成几条结构化的经验记录。这里有个容易踩的坑:如果把原始对话全量塞进记忆,记忆体很快膨胀,检索质量断崖式下降。
2.2 记忆层是进化的黑匣子也是命门
记忆层在整个框架里地位最特殊,它既是agent的长期存储,也是反思引擎的输入来源。Hermes Agent的常见实现是三层记忆:工作记忆(当前会话上下文窗口)、向量记忆(历史经验的语义检索)、结构化记忆(用户偏好、任务类型的规则型记录)。工作记忆就是普通的上下文窗口,不需要额外解释;向量记忆需要依赖embedding模型,把经验文本切成块之后向量化存储;结构化记忆则是把可量化的偏好写进JSON或数据库表。
实际落地时,向量记忆最容易出问题。embedding模型的选择直接决定检索质量,但很多部署教程只告诉你要配embedding_model,没告诉你不同模型的向量维度不同,一旦中途换模型,旧的向量库全部作废。我踩过这个坑:第一版用了一个256维的embedding模型跑了两天,后来为了提升精度换成768维的,结果检索接口直接报维度不匹配,最后只能清空向量库重新灌数据。所以在你准备把Hermes Agent-main部署到正式环境前,先把embedding模型定死。
结构化记忆的典型落地形态是用户画像文件。要调参时建议先找到类似profile.json的文件,里面会记录比如「用户偏好python实现」「用户要求代码必须带注释」这类规则。agent在每次决策前会读取这个文件,作为系统提示词的一部分注入。这部分是「进化」的直接体现:任务是新的,但用户偏好是历史积累的,agent天然具备个性化能力。
2.3 反思机制:什么时候触发「进化」,触发后写什么
反思是自我进化框架里最像「人」的模块,因为在常见设计里它不是每轮都触发,而是满足特定条件才触发,这也是控制成本的关键。Hermes Agent里常见的触发条件有三类:一是任务完成且存在明确结果时;二是任务连续失败N次时;三是距离上次反思超过一定时间或任务数时。我个人的建议是,默认采用「任务完成即反思,但反思输出要压缩」的策略。
反思输出什么内容也很重要。从源码设计的角度看,反思结果一般会拆成三部分:what_worked(这次任务里有效的做法)、what_failed(无效甚至有害的做法)、next_action(下一次应该尝试的具体动作)。next_action是进化的核心驱动力,它会被技能库消费掉。如果配置不当,比如反思只输出感受不给行动项,那进化就停留在纸面上。
提示:判断一个自称自我进化的agent框架是否合格,就看它的反思输出有没有被「执行」的通道。只有反思没有行动注入,就只是日志分析,谈不上进化。
3. 把 Hermes Agent-main 源码跑起来:环境搭建与最小启动命令
3.1 拿到源码后先别急着 install,先核对运行环境
Hermes Agent-main 这个目录名一看就是从 GitHub 主分支拉下来的源码包。解压之后先别急着pip install -r requirements.txt,我吃过这个亏:直接装依赖把 Python 3.12 环境里一堆包升级坏了。正确的顺序是:先开一个干净的虚拟环境,再看requirements.txt里的依赖锁定范围,最后确认 Python 版本。
这类 agent 框架对 Python 版本通常比较挑剔,常见要求是 3.10 或 3.11。如果你的机器默认是 3.12,建议用pyenv或conda建一个 3.11 的干净环境。下面是我在本地跑通的最小命令序列:
# 1. 用 conda 创建隔离环境,Python 版本按项目要求选 3.11 conda create -n hermes-agent python=3.11 -y conda activate hermes-agent # 2. 进入源码根目录(目录名就是 Hermes Agent-main) cd Hermes\ Agent-main # 3. 先安装核心依赖,注意看安装日志里是否有编译报错 pip install -r requirements.txt这三个命令做完,你的环境基本就位了。为什么强调requirements.txt而不是pip install仓库里的 setup.py?因为在源码落地阶段,依赖版本锁定期比什么都重要,尤其是 pydantic 和 langchain 这类跟 agent 框架强相关的包,版本漂移会让 API 调用行为直接变掉。
如果 conda 还没有装,可以用系统 Python 的venv替代,但要注意:python3.11 -m venv .venv这种写法依赖系统里已有对应 Python 版本,没有的话还是得先解决解释器问题。这里没有捷径,不要用系统全局环境硬跑。
3.2 最小配置:用 deepseek 等国产模型的 API 把对话跑通
环境装好后最让人没底的一步就是配置 LLM 后端。Hermes Agent-main 的常见设计是走 OpenAI 兼容接口,这样可以让它接任意具备 OpenAI 兼容 API 的模型服务。我在做选型时最先试的就是 deepseek,原因很简单:接口兼容度高,且 token 成本远低于闭源商业模型,适合拿来做框架验证。
找到源码里的.env.example文件,复制成.env之后按下面格式改:
# 模型服务商的外网 HTTP 基础地址,deepseek 的地址按官网填 LLM_BASE_URL=https://api.deepseek.com/v1 # 对应平台的 API Key,建议用环境变量引用而不是写死在代码里 LLM_API_KEY=sk-xxxxxxxxxxxxxxxx # 对话模型名称,这里选 deepseek-chat 就够跑通框架流程 LLM_MODEL_NAME=deepseek-chat # 温度参数:0.2 偏低,让 agent 行为更稳定 TEMPERATURE=0.2这里有两个容易被忽视的点。第一,LLM_BASE_URL必须带/v1后缀,很多服务商兼容端点和原生端点不一样,漏掉后缀会 404;第二,TEMPERATURE这个参数对 agent 进化影响极大,我建议先在 0.2 左右跑通流程,稳定之后再逐步调高。温度过高会让反思输出天马行空,进化方向不可控。
配置好.env后可以先用一段简单的 Python 片段验证 API 连通性,确保不是框架问题而是配置问题:
import os from openai import OpenAI # 从 .env 读取配置,这里用 os.environ 模拟 dotenv 的加载结果 client = OpenAI( base_url="https://api.deepseek.com/v1", api_key=os.environ["LLM_API_KEY"], ) response = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": "请回复一句话验证连接"}], temperature=0.2, ) print(response.choices[0].message.content)这段代码的作用是把框架排除在怀疑列表之外。如果这段能通,说明你的.env配置没问题,问题只可能出在框架内部;如果这段不通,就回头检查 API Key 和后缀。把问题边界切干净再启动 agent,能省掉大量「玄学排错」时间。
3.3 启动 agent 的三种方式与对应命令
跑通 API 之后,启动 Hermes Agent 的方式通常取决于你手里的入口文件。常见做法是源码里带一个main.py或cli.py,用命令行传参数指定运行模式。我一般把启动方式分成三种:交互式对话、单次任务执行、后台服务化。
交互式对话用于快速验证 agent 是否具备基本对话与工具调用能力:
python main.py --mode chat单次任务执行用于测试反思与记忆闭环,适合跑批量实验:
python main.py --mode run --task "统计当前目录下所有 python 文件的行数" --task-id 001后台服务化用于接入自己的业务系统,常见做法是把它包装成 FastAPI 服务:
uvicorn server:app --host 0.0.0.0 --port 8000三种方式的差别在于任务边界。交互模式里 agent 的状态是连续翻涌的,适合人工观察;单次任务执行模式里每次任务有明确边界,反思引擎会在任务结束时触发,是验证「进化」最好的模式;服务化模式则是把 agent 的记忆与技能能力暴露成接口,让外部系统调用。如果你的目标是评估自我进化能力,请优先用--mode run,这样每次任务的产出物都在同一份记忆磁道上累积,观察起来最直观。
提示:启动后如果一直卡在「正在连接到模型服务」这一步,优先检查
.env里的LLM_BASE_URL是否被代理或防火墙拦了,而不是去源码里找问题。
4. 让智能体「真正进化」:记忆、技能注册与反思周期的参数设置
4.1 记忆配置:top_k、相似度阈值与记忆分层
当你能用--mode run跑通任务之后,进化的质量就取决于记忆配置。记忆模块最常见的配置文件是memory.yaml,里面有几个参数属于「一调一个效果」的关键项。第一个是top_k,它控制每次决策前从向量记忆里检索多少条历史经验注入上下文;第二个是similarity_threshold,它控制检索结果的最低相似度,低于阈值的纪要会被丢弃;第三个是memory_ttl,控制记忆有效期的天数。
我这里给出一份我实际用过的配置骨架:
# 向量记忆检索配置 vector_memory: top_k: 5 similarity_threshold: 0.72 embedding_model: "BAAI/bge-small-zh-v1.5" # 结构化记忆配置 structured_memory: profile_file: "data/user_profile.json" ttl_days: 30参数top_k我为什么选 5 而不是 10?因为经验文本灌入上下文后会挤占指令空间。一个 agent 的上下文窗口是固定的,注入 10 条历史经验意味着留给当前任务的 token 变少。similarity_threshold我调过 0.5、0.7、0.8 三档,0.5 会混入大量无关历史导致 agent 行为紊乱,0.8 则可能让大多数任务检索不到历史经验,0.72 附近是覆盖率和精度的折中区间。
embedding 模型的选型也属于记忆配置的一部分。BAAI/bge-small-zh-v1.5是我在中文任务上相对常用的默认选项,它只有 512 维,检索速度够快。如果你的任务偏英文,可以换成text-embedding-3-small,但要记住换模型等于换向量空间,旧向量库必须重建,这事的成本提前算进去。
4.2 技能库自动注册:什么条件下允许 agent 自己写工具
「自我进化」最激进的能力是 agent 自己注册新工具。在 Hermes Agent-main 这类框架里,技能库通常表现为一组 Python 函数或 JSON 描述的工具清单,agent 在反思阶段发现现有工具不足以解决某类任务时,会生成一个新的工具描述并写入技能库。这是一把双刃剑:注册对了效率翻倍,注册错了污染整个工具候选列表。
我在实操中建议把技能注册拆成两级:手动审批和全自动。方式是在skills.yaml里加一个registration_mode字段:
# 技能库配置 skill_library: registration_mode: "approval" # approval 或 auto max_skills: 200 allowed_imports: ["json", "csv", "pathlib", "os"]approval模式会让 agent 把新技能写到pending_skills/目录,由你人工过一遍再移入正式目录;auto模式则直接写入。我见过一个团队用auto模式跑了三周,技能库膨胀到 500 多个工具,每次工具选择都要经过大模型做长文本分类,速度慢了一倍。所以我的建议是:起步期用approval,跑熟了再按命名空间局部放开auto。
max_skills参数是很关键的上限防护阀。技能库不是为了无限膨胀,而是为了高效复用。当接近上限时,合适的做法是触发一次旧技能清理,把连续 N 次没有被调用的工具标记为废弃。如果你在源码里找skill_cleanup或archive_skill这类入口,一般就是干这个的。
4.3 反思与自我进化的触发条件:频率、深度、收益权衡
反思频率和高层策略是进化收敛快慢的调节阀门。配置层面常见参数有两个:reflection_interval和reflection_depth。前者控制每执行多少次任务触发一次反思,后者控制反思输出的详细程度。默认值通常分别是 1 和 3,但实际业务里不一定合适。
# 反思引擎配置 reflection: interval_tasks: 1 # 每完成 1 个任务触发一次 depth: 2 # 反思输出深度:1 只记结论,2 记结论+行动项,3 记录完整推理 max_reflection_length: 600 # 单条反思的最大 token 数interval_tasks设成 1 是最激进的做法:每个任务结束都反思。这在任务类型一致、重复度高的场景下效果好,比如数据清洗、日志解析,因为下一轮几乎一定用得上;但在任务五花八门的场景下,过频的反思会拉低执行效率。如果你的业务是客服类或文档处理类,建议改成 3 或 5。depth控制的是长尾质量。depth=2是我觉得性价比最高的档位,既有行动项又不至于让反思比任务本身还长。
max_reflection_length是我后来才注意到的关键参数。反思文本如果过长,写进记忆库后检索时占用的 token 也会变长。有些反思内容会演变成大模型的「自我感动式输出」,缓解办法就是用一个长度上限把反思压成结构化摘要。
注意:不要为了追求「高级进化感」把反思参数拉满。反思本身要消耗大模型调用次数和 token 费用,进化效果边际递减,成本却是线性上升的。我的习惯是先按小参数跑一周,看记忆库里的经验质量再决定要不要加深度。
5. 源码落地避坑指南:从部署到进化的 5 个常见翻车现场
5.1 现象:pip install 秒失败,解析依赖时卡在 pydantic
现象是执行pip install -r requirements.txt时报依赖冲突,或安装到一半提示pydantic_core编译失败。原因通常有两个:Python 版本太高,或者 pydantic 与环境中已存在的 langchain 版本冲突。比较常见的组合是 Python 3.12 加新版本 pydantic v2,会导致部分较低优先级的依赖包编译不过。
解决:创建一个全新虚拟环境并固定 Python 3.11;若仍然冲突,手动把pydantic固定在2.5.x以下或按 requirements 里标注的版本装。检查依赖树可以用pip check验证是否还有冲突。这套组合拳能解决七成以上的安装问题。
5.2 现象:启动时报 embedding dimension 不匹配
现象是 agent 能跑,但第一次做记忆检索时抛出类似dimension mismatch的错误。原因大概率是你中途换过 embedding 模型,或者memory.yaml里配置的 embedding 模型和向量库底层存的维度不一致。
解决:如果数据量不大,直接删掉向量库目录重建,这是最快的「后悔药」;如果已经积累了很多记忆,就写一个批量重灌脚本,把原始文本重新切块、向量化后写入新库。更严谨的做法是在启动时做一次自动维度校验,Hermes Agent-main 里如果留了check_vector_db()这类入口就调用它,没有就自己写 10 行校验代码。教训就是:embedding 模型一旦选定,不要频繁更换。
5.3 现象:agent 启动后一直转圈,日志里没有任何报错
这应该是 agent 落地中最玄学的坑。现象是启动后请求发出去,长时间没有响应,日志停在某个状态不往下走。原因一般是模型服务端的连接超时设置太长,或者 LLM 服务商对并发有限制,又或者是.env里TIMEOUT参数没设。默认情况下框架可能给了一个很大的超时值,出错后重试机制掩盖了真实失败。
解决:优先缩短超时时间并开启详细日志,用如下命令启动并观察:
python main.py --mode run --task "测试任务" --verbose --timeout 3030 秒内如果没响应,大概率是上游 API 问题,而不是挂死。也可以把日志级别从 INFO 调到 DEBUG,看请求体到底发去了哪个地址。有时候 base_url 写错,但并不报错,因为服务端直接把这个请求当成非法请求处理了,表现为卡住或无限重试。
5.4 现象:记忆文件越滚越大,检索越来越慢
现象是跑了几天后,agent 的响应速度明显变慢,尤其是每次决策前那一段「检索记忆中」的过程。原因很简单:向量库和结构化记忆文件持续膨胀,而你没有做任何归档或淘汰。框架默认配置通常偏向于「全量保留」,这在长线运行下不现实。
解决:给记忆加上分层清理策略。结构化记忆设置 TTL(比如用户画像 30 天没用就归档到冷存储),向量记忆定期做摘要压缩——把多条相似经验合并成一条。源码里如果有consolidate或compress_memory的入口就用;没有就自己写个脚本,定期按 title 相似度做聚类并保留代表项。这个步骤是唯一能让你长期运行不翻车的操作,不要偷懒。
5.5 现象:自我进化把上下文窗口吃光,token 费用翻倍
现象是进化跑得越久,单次任务的 token 消耗越高,账单肉眼可见地涨。原因是注入的「历史经验」和「技能库描述」越来越多。top_k设了 5 但每一条经验都很长,技能库 200 个工具的描述全部塞进系统提示词,上下文窗口被挤得只剩下少量空间给当前任务。
解决:先砍技能库描述的长度,把工具描述压缩成一句话;再对历史经验做摘要后再注入,而不是把原文塞进去。另一个有效手段是给注入的经验设置总预算,比如max_context_prefix_tokens: 1500,超出部分由检索模块做截断。这类参数一般都会在 agent 框架的上下文配置里留口子,找到并约束它,token 大头才能压下来。
6. 怎么验证你的 Hermes Agent 真的在进化
6.1 用一轮对照实验量化进化
「自我进化」不能靠感觉验证,我的做法是设计一组严格的对照实验。同一份任务列表,准备两份完全相同的 agent 配置,唯一差别是 A 开启记忆与反思,B 关闭进化相关模块,然后跑相同题集,记录三组指标:任务成功率、平均执行轮数、平均耗时。连续跑三轮后对比趋势。
如果 A 的成功率明显上升,而 B 没有,说明进化的确在起作用;如果两者都在上升,说明你的任务集太简单,agent 用模型先验就够了,记忆系统反而是多余的。为了减少人工干预,可以用一个简单的 Python 脚本做统计:
import json # 读取每轮任务的评测结果,字段按自己记录方式调整 results = json.load(open("eval_results.json")) for run_id, run in results.items(): success_rate = sum(r["success"] for r in run["tasks"]) / len(run["tasks"]) avg_steps = sum(r["steps"] for r in run["tasks"]) / len(run["tasks"]) print(f"第{run_id}轮 成功率={success_rate:.2%} 平均轮数={avg_steps:.2f}")把这组数字按轮次画成趋势线,比任何「感觉它变聪明了」都可信。我自己的经验是:如果前三轮成功率从 40% 涨到 70%,之后就卡住不动了,说明进化遇到了瓶颈,瓶颈大概率在技能库数量而不是反思频率上。
6.2 把记忆快照当变更管理来用
另一个好用的验证方法是把记忆库的快照当成代码仓库来管理。每周导出一份完整的记忆与技能库快照,对比两次快照的差异,就能看出 agent 这周新增了哪些技能、哪些记忆被改写、哪些旧技能被淘汰。这在排查「进化跑偏」时尤其有用:如果 agent 的技能库在短短几天内新增了一批你根本不认识的工具,说明反思引擎失控了,快照对比能第一时间定位到是哪一次任务引入了这个技能。
快照操作通常就是压缩记忆目录并加时间戳命名:
tar -czf memory_snapshot_$(date +%Y%m%d).tar.gz memory/ skills/ data/我最早犯的错就是把进化当作一个「开了就不用管」的自动化功能,结果第三周技能库失控,工具候选列表里混进了一堆任务无关的脚本。现在养成的习惯是每周做一次快照,每月做一次技能清理;进化越激进,审查越要频繁。这个方向值得投入,但它不是玄学,是要用工程手段去收敛的。希望这篇笔记能让你跑通这套框架时少走几段我走过的弯路。
提示:第一次看快照差异时不用追求所有项都合理,重点看新增技能的来源链路:哪一次反思、基于哪个失败经验、生成了什么工具。链路完整才说明进化是真闭环,链路断了就只是模型在输出一些未被消费的文本。
本文还有配套的精品资源,点击获取