1. 为什么你的 Agent 每次重启都像失忆:从 Workspace 目录结构说起
如果你正在用 AgentScope 搭一个能长期干活的 Agent,大概率遇到过这种尴尬:昨天刚跟它聊清楚的项目背景、用户偏好、接口约定,今天重启进程,它一脸茫然地反问你「请问您指的是哪个项目」。这不是模型不行,而是你没有给它一张固定的「办公桌」——也就是 Workspace。
AgentScope 的 Workspace 本质上是一个约定优于配置的目录,Agent 的人格、长期记忆、领域知识、技能、子 Agent 声明、会话记录全部以文件形式落盘。每次推理前,框架通过 Hook 把这些文件内容注入 System Prompt;每次调用结束后,再把新的记忆和会话写回磁盘。理解了这套「上班读文件、下班写文件」的机制,你就能把 Agent 从「一次性对话玩具」变成「可复现、可迁移、可审计的生产组件」。
这篇聚焦三件事:一是把 Workspace 的目录树和每个文件的职责讲透,二是给出可以直接复制粘贴的 AGENTS.md、MEMORY.md、KNOWLEDGE.md 配置骨架,三是演示启动后如何验证加载顺序、记忆读写是否真的生效。适合已经跑通过 AgentScope 最小 Demo、准备把 Agent 工程化的同学。前置只需要你了解 Hook 机制和 Agent 调用流程,没读过架构篇也不影响,本文会把关键点补齐。
我试过把人格、记忆、知识全塞进一个超长 System Prompt,结果是 token 爆炸、维护困难、改一行要动全身。Workspace 的价值就在于把这些关注点拆成独立文件,各管各的,改人格不动记忆,加知识不动人格。
2. Workspace 目录树与 AGENTS.md、MEMORY.md 的职责边界
先把完整目录树贴出来,这是你后面所有配置的「地图」。默认路径是.agentscope/workspace,你也可以在构建 Agent 时用.workspace(Paths.get("..."))指定到任意位置。
.agentscope/workspace/ ├── AGENTS.md # 人格定义,每次推理都注入,无长度限制 ├── MEMORY.md # 长期核心记忆,每次注入,受 token 预算限制 ├── knowledge/ │ ├── KNOWLEDGE.md # 知识入口目录,告诉 Agent 有哪些资料 │ ├── faq.md # 常见问题解答 │ ├── product-guide.md # 产品指南 │ └── troubleshooting.md # 故障排查手册 ├── memory/ │ ├── 2024-01-15.md # 每日记忆流水账,运行时自动写入 │ ├── 2024-01-16.md │ └── .consolidation_state # 记忆整理器内部状态,别手动改 ├── skills/ │ └── <skill-name>/SKILL.md # 自定义技能定义 ├── subagents/ │ └── <id>.md # 子 Agent 声明,自动发现 └── agents/<agentId>/ ├── workspace/ # 隔离子 Agent 的运行时根目录 └── sessions/ ├── sessions.json # 会话索引:id / summary / updatedAt ├── <sessionId>.jsonl # LLM 可见的压缩上下文 └── <sessionId>.log.jsonl # 完整对话日志,用于审计AGENTS.md 是工牌,MEMORY.md 是核心笔记,两者别混。AGENTS.md 定义「我是谁、我该怎么做」,比如身份、行为准则、能力范围,它每次推理都完整注入且没有长度限制,所以你可以写得详细,但别写成小说。MEMORY.md 是「整理过的核心记忆」,同样每次注入,但有 token 预算(默认 8000),超出会被截断并追加提示让 Agent 用memory_search查历史。一个管人格,一个管记忆,职责清晰。
knowledge/ 和 MEMORY.md 的区别要拎清。knowledge/ 是书架,KNOWLEDGE.md 只是目录,告诉 Agent「有哪些书可以查」,具体内容按需读取,不占常驻 token。MEMORY.md 是 Agent 个人的经验和偏好,是常驻的。大文件、参考手册、产品文档一律放 knowledge/,别往 MEMORY.md 里塞。
memory/ 是日记本,不自动注入。每天一个YYYY-MM-DD.md,由运行时写入,属于流水账。它和 MEMORY.md 的关系是:日记积累到一定程度,由整理器压缩提炼进 MEMORY.md。.consolidation_state记录整理进度,属于内部状态,不要手动编辑。
两层读写机制是理解 Workspace 的关键。读取时先查 AbstractFilesystem(云端/多租户共享存储),没找到再兜底读本地磁盘;写入时默认写共享层,共享层出问题才写本地。注意顺序是「先云端后本地」,不是反过来,因为云端可能有其他实例刚写入的最新数据。这个设计在多租户场景下尤其重要。
3. 可复制的配置骨架:AGENTS.md、MEMORY.md 与 HarnessAgent 构建
这一节给你三份可以直接落盘的文件,以及对应的 Java 构建代码。先建目录:
mkdir -p .agentscope/workspace/{knowledge,memory,skills,subagents} cd .agentscope/workspace touch AGENTS.md MEMORY.md knowledge/KNOWLEDGE.mdAGENTS.md 骨架,直接复制,按需改:
# 我是订单客服助手小美 ## 身份 我是一个友好的客服助手,专门帮助用户解决订单相关问题。 服务对象是电商平台的注册用户,语气亲切但不啰嗦。 ## 行为准则 1. 先确认用户身份,再处理具体请求 2. 礼貌回复,遇到情绪激动的用户先安抚 3. 无法解决的问题,明确告知并转接人工客服 4. 不编造订单信息,查不到就如实说 ## 能力范围 - 查询订单状态 - 处理退款申请 - 修改收货地址 - 解释退换货政策 ## 输出格式 - 涉及金额、订单号时用代码块包裹,方便用户复制 - 步骤类回答用有序列表MEMORY.md 骨架,记住「重要内容放前面」,因为超预算时是从后往前截断的:
# 长期记忆 ## 用户偏好 - 张先生喜欢用邮件沟通,回复时附上订单号 - 李女士每次下单都要加急,优先推荐顺丰 ## 重要事件 - 2024-01-15:系统升级,暂停服务 2 小时 - 2024-01-20:新产品上线,退款政策同步调整 ## 已知坑 - 跨境订单的物流查询接口偶尔超时,需重试一次KNOWLEDGE.md 骨架,它只是目录,正文放同目录的其他文件:
# 知识库目录 以下文件可按需读取: - faq.md:常见问题解答,覆盖 80% 的咨询场景 - product-guide.md:产品使用指南,含图文说明 - troubleshooting.md:故障排查手册,按错误码索引HarnessAgent 构建代码,把上面这些串起来:
HarnessAgent agent = HarnessAgent.builder() .name("MyAgent") .model(model) .workspace(Paths.get(".agentscope/workspace")) .additionalContextFile("SOUL.md") // 额外注入的文件,可多个 .additionalContextFile("PREFERENCES.md") .maxContextTokens(8000) // MEMORY.md 的 token 上限 .build();配置项对照表,方便你按场景调:
| 配置项 | 作用 | 默认值 |
|---|---|---|
| workspace | 工作空间根目录 | .agentscope/workspace |
| additionalContextFile | 额外注入 System Prompt 的文件 | 无 |
| maxContextTokens | MEMORY.md 最大 token 数 | 8000 |
如果你用 Claude Code 或 Cline 这类工具做本地开发,想让它们也遵循同一套人格和记忆约定,可以把 Base URL、API Key、Model ID 三件套统一配置。Base URL 填https://taotoken.net/api,Key 在控制台生成,Model ID 按你实际用的模型填。这样编辑器里的补全和 Agent 运行时读的是同一份 AGENTS.md,行为一致。
4. 启动后验证:加载顺序、记忆读写是否真的生效
配置写完不代表生效,必须验证。这一节给你一套可执行的验证动作,覆盖加载顺序和记忆读写两个维度。
第一步,验证工作空间被识别。启动 Agent 后打印工作空间路径:
System.out.println(agent.getWorkspace()); // 期望输出:.agentscope/workspace如果输出的是默认路径而不是你配置的路径,说明.workspace()没生效,检查路径字符串是否写错。
第二步,验证 System Prompt 注入。把日志级别开到 DEBUG,观察推理前的注入内容。你会看到类似这样的结构:
## Session Context - 当前日期:2024-01-15 - 工作空间路径:.agentscope/workspace - 会话ID:session-12345 ## Workspace Guidance <loaded_context> <agents_context>[AGENTS.md 全文]</agents_context> <memory_context>[MEMORY.md 内容]</memory_context> <domain_knowledge_context> [KNOWLEDGE.md 内容] 可用文件列表:faq.md, product-guide.md, ... </domain_knowledge_context> </loaded_context>重点看三处:agents_context里是不是你写的 AGENTS.md 全文,memory_context里是不是 MEMORY.md 的内容,domain_knowledge_context里有没有列出 knowledge/ 下的文件。缺哪个就查哪个文件是不是没建对。
第三步,验证记忆写入。跟 Agent 对话几轮,然后检查memory/目录:
ls -la .agentscope/workspace/memory/ cat .agentscope/workspace/memory/2024-01-15.md正常情况下会生成当天的YYYY-MM-DD.md,里面是这轮对话提炼出的记忆条目。如果目录是空的,说明 MemoryFlushHook 没触发,检查你的 Hook 注册顺序。
第四步,验证会话持久化。检查 sessions 目录:
cat .agentscope/workspace/agents/<agentId>/sessions/sessions.jsonsessions.json里应该有本次会话的 id、summary、updatedAt。<sessionId>.jsonl是 LLM 可见的压缩上下文,<sessionId>.log.jsonl是完整日志。两者都在,说明 SessionPersistenceHook 工作正常。
第五步,验证 token 预算截断。故意往 MEMORY.md 里塞超长内容,重启后看注入的memory_context末尾有没有出现... (memory truncated — use memory_search for older entries) ...。出现说明截断机制生效,Agent 也知道该用memory_search查历史。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
配置过程中最容易撞上的几类报错,逐个拆。
401 Unauthorized。最常见,八成是 API Key 没配对或过期。检查你的 Key 是不是从控制台正确复制,有没有多余空格。如果你用的是统一接入方式,确认 Base URL 填的是https://taotoken.net/api,Key 和 Model ID 三件套要配套,缺一个都会 401。另外注意 Key 有没有被环境变量覆盖,echo $YOUR_API_KEY看一眼实际值。
local proxy failed。这个报错通常出现在你本地起了转发层但配置没对齐。先确认转发进程是否在跑,再确认 Agent 的 Base URL 指向的是转发地址而不是直连地址。如果你没打算用转发,直接把 Base URL 改成https://taotoken.net/api即可,别让中间层成为故障点。
Error reading choices / reading choices 相关。这类报错一般出现在解析模型返回时,返回体不是预期的 JSON 结构。常见原因有三个:一是 Model ID 填错,请求打到了不兼容的端点;二是返回被中间层改写过;三是流式和非流式配置不匹配。先确认 Model ID 和你的 Key 权限匹配,再用 curl 直接打一次接口看原始返回:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"your-model-id","messages":[{"role":"user","content":"hi"}]}'如果 curl 能返回正常 JSON,问题就在 Agent 侧的解析配置;如果 curl 也报错,问题在 Key 或 Model ID。
OAuth 相关报错。如果你用的是需要 OAuth 的客户端(比如某些 CLI 工具),报错通常指向 token 过期或回调地址不匹配。检查你的 OAuth 配置里的回调地址是否和客户端注册的一致,token 是否需要刷新。对于 Codex 这类用auth.json的工具,确认文件里的字段完整,Base URL、Key、Model ID 三件套齐全,缺字段会直接报 OAuth 失败。
AGENTS.md 没生效但没报错。这是最隐蔽的。WorkspaceManager 在 validate 时对缺失的 AGENTS.md 只 warn 不报错,Agent 照样能跑,只是丢了人格。所以启动后一定要按第 4 节的第二步确认注入内容,别等线上发现 Agent「性格变了」才回头查。
6. 把 Workspace 用成工程资产:从可复现到可迁移
Workspace 真正的价值不在单次运行,而在可复现和可迁移。你把 AGENTS.md、MEMORY.md、knowledge/ 一起提交到 Git,换台机器 clone 下来,Agent 的人格和知识完全一致。MEMORY.md 可以按环境分文件,开发环境用一份、生产环境用另一份,通过additionalContextFile切换。
日常维护上,我的习惯是:AGENTS.md 改动走 code review,因为它是人格契约;MEMORY.md 定期人工审一遍,把过时条目删掉,别让它无限膨胀;knowledge/ 按业务模块分文件,KNOWLEDGE.md 只维护目录;memory/ 里的旧日记按月归档到memory/archive/,避免文件数过多拖慢列表操作。
如果你要把这套 Workspace 接入长期运行的编码 Agent,建议配合 Coding Plan 使用,把人格、记忆、技能都沉淀成文件,Agent 换会话也不丢上下文。需要生成或管理 Key 时去 API Keys 页面,接入细节查接入文档,想先验证模型行为可以直接在模型对话里试。把 Workspace 当成 Agent 的固定资产来经营,它才会越用越懂你。