news 2026/9/28 18:19:13

AI Agent框架探秘:拆解 OpenHands 的 Memory 模块与配置实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent框架探秘:拆解 OpenHands 的 Memory 模块与配置实践

1. OpenHands Memory 模块到底解决什么问题

如果你正在用 OpenHands 搭 AI Agent,大概率遇到过这种尴尬:第一轮对话里 Agent 记住了项目路径、依赖版本、你偏好的代码风格,第二轮换个任务它就像失忆一样从头问起。这不是模型笨,而是 Memory 模块没配对。OpenHands 的 Memory 模块本质上是给 Agent 装一个「可插拔的记事本」——它决定哪些信息进短期上下文、哪些落盘成长期记忆、哪些在任务切换时被压缩或丢弃。

我试过把 Memory 当成单纯的向量库来用,结果 Agent 在长任务里反复读取同一份文件摘要,token 烧得飞快。后来才明白 OpenHands 的 Memory 是分层设计的:工作记忆(Working Memory)负责当前 session 的即时上下文,长期记忆(Long-term Memory)通过外部存储做跨 session 持久化,而配置层则决定两者的读写策略。对开发者来说,真正要动手改的是config.toml里的 memory 段和 embedding 通道。

这篇面向正在搭建 AI Agent 的开发者,给出可直接复制的config.toml骨架、TaoToken 统一 Key/API 通道的接入示例,以及 Memory 读写验证动作。跑通之后,你的 Agent 就能在多次任务之间保持记忆连续性,而不是每次从零开始。

2. TaoToken 前置:统一 Key 与 API 通道

OpenHands 的 Memory 模块在做 embedding 和摘要压缩时,需要调用模型接口。如果你同时用多家模型,Key 管理会变得很乱。TaoToken 提供统一 Key 和 API 通道,把模型对话、embedding、coding plan 等入口收敛到一个 base_url 下,配置时只需要改一处。

官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=

API 地址(不加 UTM):https://taotoken.net/api

你需要先拿到 API Key,然后把它写进 OpenHands 的环境变量或config.toml。注意不要把 Key 硬编码进代码仓库,用.env或系统环境变量注入。

2.1 获取 API Key

进入控制台创建 Key:

https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api_keys

创建后复制 Key,形如sk-xxxx。这个 Key 同时用于模型对话和 embedding 请求,不需要为每个模型单独申请。

2.2 确认模型与通道

在模型对话页可以测试 Key 是否可用:

https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model_chat

如果你打算长期跑编码类 Agent,可以了解 Coding Plan:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding_plan

接入文档在这里,配置字段有疑问时对照查:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

3. 可复制配置:config.toml 骨架与 Memory 参数

OpenHands 的配置文件通常放在项目根目录或~/.openhands/config.toml。下面这份骨架可以直接拿去改,重点看[memory]和[llm]两段。

# config.toml [core] workspace_base = "./workspace" max_iterations = 50 cache_dir = "./cache" [llm] # TaoToken 统一通道 base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" model = "claude-sonnet-4-20250514" temperature = 0.2 max_output_tokens = 4096 [memory] # 工作记忆:当前 session 保留的最近消息条数 working_memory_size = 20 # 长期记忆:是否启用持久化 enable_long_term = true # 持久化后端:local / redis / sqlite backend = "sqlite" # sqlite 文件路径 storage_path = "./memory/openhands_memory.db" # embedding 模型,走同一个 TaoToken 通道 embedding_model = "text-embedding-3-small" embedding_base_url = "https://taotoken.net/api" embedding_api_key = "${TAOTOKEN_API_KEY}" # 记忆压缩阈值:超过多少 token 触发摘要 summarize_threshold = 8000 # 检索返回的 top-k 记忆片段 retrieval_top_k = 5 [agent] # 是否在任务切换时保留记忆 persist_memory_across_tasks = true # 记忆写入策略:always / on_task_end / manual memory_write_policy = "on_task_end"

几个参数的实际影响,我按踩过的坑说明:

working_memory_size设太大,上下文会膨胀,模型响应变慢;设太小,Agent 会忘记刚看过的文件内容。20 到 30 是比较稳的区间。

summarize_threshold决定什么时候把旧消息压缩成摘要。如果你跑的是长任务,比如重构一个模块,这个值可以调到 12000,避免频繁摘要丢失细节。

memory_write_policy设为on_task_end时,只有任务结束才落盘。如果你希望 Agent 在任务中途也能记住关键决策,改成always,但写入频率会上升。

backend选sqlite适合本地开发,零依赖。如果多 Agent 共享记忆,换成redis,把storage_path改成 Redis 连接串。

3.1 环境变量注入

不要把 Key 写进 toml。在 shell 里导出:

export TAOTOKEN_API_KEY="sk-你的实际Key"

Windows PowerShell:

$env:TAOTOKEN_API_KEY="sk-你的实际Key"

然后启动 OpenHands 时它会自动读取。

4. 验证请求:Memory 读写链路跑通

配置写完,必须验证 Memory 真的在读写,而不是只加载了配置。下面分三步:启动、写入、检索。

4.1 启动并检查 Memory 初始化

python -m openhands.core.main --config config.toml

启动日志里应该出现类似:

[Memory] backend=sqlite path=./memory/openhands_memory.db [Memory] long_term=enabled embedding_model=text-embedding-3-small [LLM] base_url=https://taotoken.net/api model=claude-sonnet-4-20250514

如果看到long_term=disabled,说明enable_long_term没生效,检查 toml 缩进和字段名。

4.2 写入一条记忆

在 OpenHands 交互界面里发一条带明确事实的消息,比如:

记住:本项目使用 Python 3.11,依赖管理用 uv,测试框架是 pytest。

任务结束后,检查 sqlite:

sqlite3 ./memory/openhands_memory.db "SELECT id, substr(content,1,80), created_at FROM memories ORDER BY id DESC LIMIT 5;"

应该能看到刚写入的记录。如果没有,检查memory_write_policy是否为on_task_end且任务确实结束了。

4.3 检索验证

新开一个 session,问:

本项目用什么测试框架?

Agent 应该回答pytest,而不是说不知道。如果答错,说明检索没命中。可以手动调 embedding 接口确认通道正常:

curl https://taotoken.net/api/v1/embeddings \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"text-embedding-3-small","input":"本项目使用 pytest"}'

返回里应该有data[0].embedding数组。如果报 401,Key 不对;报 404,base_url 路径写错,注意是https://taotoken.net/api而不是带/v1的旧写法。

5. 本篇常见错排查

5.1 Memory 写入成功但检索不到

最常见原因是 embedding 维度和检索时不一致。比如写入时用了text-embedding-3-small(1536 维),检索时配置成了别的模型。检查config.toml里embedding_model在读写两侧是否一致。

另一个原因是retrieval_top_k太小,相关记忆排在 top-k 之外。临时调到 10 测试,确认能命中后再调回去。

5.2 启动报 base_url 连接失败

先确认网络能访问https://taotoken.net/api。如果公司网络有出口限制,联系运维放行。不要改成其他非官方地址,配置里只认这个 base_url。

如果报model not found,去模型对话页确认你用的模型名是否在当前 Key 的可用列表里:

https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model_chat

5.3 sqlite 文件锁冲突

多进程同时跑 OpenHands 时,sqlite 会报database is locked。本地开发建议单进程;需要并发就换backend = "redis",并在storage_path填 Redis 连接串,例如redis://localhost:6379/0。

5.4 记忆膨胀导致响应变慢

跑了几十个任务后,memories表可能上万条。加一个定期清理策略,比如只保留最近 30 天的记忆:

DELETE FROM memories WHERE created_at < datetime('now', '-30 days');

或者在config.toml里加max_memory_entries = 5000,让 OpenHands 自动淘汰旧记录。

5.5 接入文档对照

字段含义拿不准时,直接查接入文档,比猜字段名快:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

6. 把记忆链路固定下来

Memory 模块配好之后,建议把config.toml纳入版本管理,但 Key 用环境变量注入。每次改完配置,跑一遍第 4 节的写入和检索验证,确认链路没断。如果你要长期跑编码类 Agent,Coding Plan 通道在长任务下的稳定性更好,可以在这里了解:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding_plan

Key 管理入口:

https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api_keys

最后一步实操建议:把memory_write_policy先设为always,跑三个连续任务,观察 sqlite 里记录的增长曲线和 Agent 的召回准确率,再决定是否改回on_task_end。这个调参过程比看文档更能让你理解 Memory 模块的真实行为。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 18:19:13

AI 超级智能体全栈项目阶段七:Spring AI 集成 MCP 全攻略:从客户端配置到服务端开发实战(含图片搜索服务案例)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 18:18:23

C++飞机大战源码模块拆解:主循环、对象管理与状态机实现

简介&#xff1a;这份源码面向C初学者与游戏开发爱好者&#xff0c;提供一套可直接编译运行的飞机大战小游戏完整工程&#xff0c;帮助读者理解2D游戏从界面绘制到逻辑控制的实现思路。压缩包共71个文件&#xff0c;约64.23MB&#xff0c;其中16个cpp源文件按版本递进组织&…

作者头像 李华
网站建设 2026/9/28 18:17:06

PCswitch 智能呼叫系统技术评测:用 TaoToken 统一 Key 打通配置链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 18:16:41

OpenClaw人人养虾:macOS 上 Gateway 的 launchd 守护与 Node 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 18:16:40

ClaudeCode+Figma-MCP 实战:前端代码精准匹配 UI 设计图的核心逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华