ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AgentScope Java Harness:3.工作区(Workspace)文件即真理,目录即架构

AgentScope Java Harness:3.工作区(Workspace)文件即真理,目录即架构 目录1. 如何优雅地驾驭长期运行的 AI Agent2. 上下文压缩让长期 Agent 永不“失忆“3. 工作区Workspace文件即真理目录即架构4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“5. 文件系统一套代码三种部署零改动切换6. 沙箱Sandbox让 Agent 在安全笼子里自由奔跑7. 子 Agent 编排 文件驱动的多智能体协作架构8. Skill技能让 Agent 从“会说话“进化为“会做事“9. Plan Mode 让 Agent 先想清楚再动手10. Channel Agent 通信的“神经系统“设计当 Agent 的所有状态都不在数据库里而是躺在一个结构化目录中时可观测、可版本化、可自我进化就不再是口号。一、引言Agent 的办公桌问题想象一下你招了一位新员工但没有给他分配办公桌、文件柜和工作手册。他每天的记忆全靠脑子上下文窗口做完的事没有归档学到的经验无处沉淀。这就是大多数裸 Agent的真实处境——**没有持久化的工作空间。**对话一结束所有中间产物、决策依据、积累的经验全部蒸发。AgentScope Java 2.0 的 Harness 模块用Workspace工作区这个概念彻底解决了这个问题Workspace 是 Agent 的唯一事实来源Single Source of Truth——人格、知识、技能、记忆、子 Agent 规格、会话历史全部以文件形式沉淀在一个结构化目录中。二、核心设计Workspace 作为唯一事实来源2.1 设计哲学Harness 的设计哲学可以用一句话概括“工作区即真理 自我进化”Agent 的所有状态不在数据库里而是在工作区目录下。这带来了三个根本性优势优势说明可观测打开文件管理器就能看到 Agent 的全部状态无需查询数据库可版本化整个工作区可以 git init每次变更都有完整的 diff 记录可自我进化Agent 自己可以修改 MEMORY.md、添加新技能实现运行时进化2.2 每次推理的自动装配Workspace 不是一个静态配置目录。它的核心机制是每次 call() 之前 │ ▼ WorkspaceContextHook │ ├── 读取 AGENTS.md → 注入人格与行为约定 ├── 读取 MEMORY.md → 注入精炼长期记忆 ├── 读取 knowledge/ → 注入领域知识 ├── 读取 skills/ → 装配可复用技能到工具集 ├── 读取 subagents/ → 加载子 Agent 规格 └── 拼装为完整 system prompt 每次 call() 之后 │ ▼ 自动回写 │ ├── 记忆日志 → memory/YYYY-MM-DD.md ├── 会话记录 → agents/agentId/sessions/ └── 任务记录 → agents/agentId/tasks/**关键点**system prompt 每轮都重新拼装。这意味着你修改工作区中的任何文件下一轮推理立即生效无需重启服务。三、目录结构约定一张图看懂 Workspaceworkspace/ │ ├── AGENTS.md ← 人格与行为约定每轮注入 system prompt ├── MEMORY.md ← 精炼长期记忆后台周期性合并维护 ├── tools.json ← MCP Server 声明 工具白名单 │ ├── knowledge/ ← 领域知识文档、参考资料 │ ├── domain-guide.md │ └── faq.md │ ├── skills/ ← 可复用技能自动装配到工具集 │ ├── code-review/ │ │ └── SKILL.md │ └──>四、AGENTS.md文件驱动的人格定义AGENTS.md 是整个工作区最核心的文件。它定义了 Agent 的人格、行为约定和工作规范。示例# Agent: TravelAssistant ## 角色定义 你是一个专业的差旅助手服务于企业员工。 ## 行为约定 - 查询航班前必须先确认出发日期和目的地 - 推荐方案时必须给出至少 2 个选项并对比价格 - 涉及报销政策时参考 knowledge/reimbursement-policy.md ## 输出格式 - 航班信息使用表格展示 - 费用估算精确到元 ## 禁止行为 - 不得直接预订只能提供建议 - 不得泄露其他用户的行程信息为什么是文件而不是代码传统方式代码/配置中心Workspace 方式文件修改人格需要重新编译/发布编辑文件立即生效只有开发者能修改产品经理、领域专家都能参与变更历史散落在 Git commit 中整个工作区天然适配 GitOps多环境同步困难复制目录即可迁移五、AbstractFilesystem逻辑与物理的优雅分离这是 Workspace 架构中最精妙的设计。5.1 问题Workspace 在逻辑上是一个统一的目录抽象但在物理上它可能存在于本机磁盘开发环境Docker 容器内沙箱隔离分布式共享存储生产多副本如果上层代码直接依赖物理路径切换部署模式就意味着大量代码修改。5.2 解法AbstractFilesystem 接口┌─────────────────────────────────────────────────────────┐ │ Workspace逻辑目录抽象 │ │ AGENTS.md · MEMORY.md · skills/ · subagents/ · ... │ └──────────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ AbstractFilesystem统一接口 │ │ readFile() · writeFile() · listDir() · delete() · ... │ └───────┬──────────────────┬──────────────────┬───────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌────────────────┐ ┌────────────────┐ │ LocalFilesystem │ │ SharedStorage │ │ DockerFilesystem │ │ (本机 Shell) │ │ (BaseStore) │ │ (沙箱隔离) │ └──────────────┘ └────────────────┘ └────────────────┘核心原则Agent 操作 Workspace 时只面向逻辑路径物理层面的读写由 AbstractFilesystem 的具体实现负责路由。5.3 三种文件系统模式模式一本机文件系统开发/个人助手HarnessAgent.builder().workspace(Path.of(./workspace)).filesystem(newLocalFilesystemSpec()).build();文件直接读写本机磁盘Shell 命令在宿主机执行适合本地开发、个人助手场景。模式二共享存储分布式多副本HarnessAgent.builder().workspace(Path.of(/workspace)).filesystem(newSharedStorageSpec().baseStore(redisBaseStore))// 或 MySQL、OSS 等.build();所有副本共享同一份工作区数据解决分布式环境下本地文件系统假设不成立的问题适合多副本部署、多用户共享。模式三Docker 沙箱安全隔离HarnessAgent.builder().workspace(Path.of(/workspace)).filesystem(newDockerFilesystemSpec().image(python:3.11).build()).build();文件操作和 Shell 命令完全在容器内执行宿主机零暴露即使 Agent 执行 rm -rf / 也不影响宿主适合处理不可信输入、多租户场景。5.4 切换零成本// 开发环境.filesystem(newLocalFilesystemSpec())// 生产环境只改一行业务代码零修改.filesystem(newDockerFilesystemSpec().image(python:3.11)) 这就是逻辑工作区与物理执行面分离的价值同一套 Agent 逻辑从个人本机一路扩到企业分布式部署只需切换文件系统配置。六、WorkspaceManager正确的文件操作姿势6.1 唯一入口所有对工作区的文件操作必须通过 WorkspaceManager// ✅ 正确通过 WorkspaceManager自动路由到当前文件系统harnessAgent.getWorkspaceManager().writeFile(output/result.txt,content);harnessAgent.getWorkspaceManager().readFile(MEMORY.md);harnessAgent.getWorkspaceManager().listDir(skills/);6.2 常见错误// ❌ 危险在沙箱或共享存储模式下会写错位置Files.writeString(Path.of(/workspace/output/result.txt),content);// ❌ 危险硬编码本机路径切换部署模式后立即失效newFile(./workspace/MEMORY.md).exists();6.3 为什么必须走 WorkspaceManager场景直接用java.nio.Files通过WorkspaceManager本机模式✅ 碰巧正确✅ 正确Docker 沙箱❌ 写到宿主机容器内看不到✅ 正确路由到容器内共享存储❌ 写到本机其他副本看不到✅ 正确路由到共享存储**结论**WorkspaceManager 是工作区操作的唯一正确入口任何时候都不应该绕过它。七、文件驱动的能力装配Workspace 不仅仅是存储它还是 Agent 能力的声明式装配中心。7.1 技能装配skills/workspace/skills/code-review/SKILL.md每个技能是一个独立目录包含 SKILL.md 描述文件。构建期框架自动扫描并装配到工具集// 技能来源可以是多源的// - workspace/skills/工作区// - Git 仓库// - Nacos 配置中心// - MySQL 数据库// - classpath 内置7.2 子 Agent 编排subagents/workspace/subagents/weather-agent.md# Subagent: weather-agent ## 职责 查询指定城市的实时天气和未来 3 天预报。 ## 工具 - get_weather(city: string, days: int) ## 输出格式 返回 JSON{city, temperature, condition, forecast[]}主 Agent 在编排时自动读取这些文件决定何时委派任务给哪个子 Agent。文件驱动 Subagent 是 2.0 推荐的多 Agent 编排方式。7.3 MCP 工具白名单tools.json{mcpServers:[{name:github,url:http://localhost:3001/mcp,allowedTools:[search_repositories,get_file_content],deniedTools:[delete_repository]}]}在工作区模式下MCP Server 的注册和工具粒度的允许/拒绝白名单都通过 tools.json 声明式配置。八、多租户隔离每个用户一个工作区在生产环境中不同用户租户的 Agent 需要完全隔离。Workspace 天然支持这一点// 每个 (userId, sessionId) 对应独立的工作区子目录// 框架自动按 RuntimeContext 中的 userId 路由HarnessAgentagentHarnessAgent.builder().workspace(Path.of(/data/workspaces)).filesystem(newSharedStorageSpec().baseStore(store)).build();// 调用时传入 RuntimeContext框架自动隔离agent.call(messages,RuntimeContext.builder().userId(user-001).sessionId(session-abc).build());隔离粒度/data/workspaces/ ├── user-001/ ← 用户 1 的完整工作区 │ ├── AGENTS.md │ ├── MEMORY.md │ └── agents/... ├── user-002/ ← 用户 2 的完整工作区完全隔离 │ ├── AGENTS.md │ └── ...九、Workspace 与其他子系统的协作Workspace 不是孤立存在的它是整个 Harness 架构的数据枢纽┌──────────────┐ │ Workspace │ └──────┬───────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 记忆系统 │ │ 压缩链路 │ │ 子Agent编排 │ │ memory/*.md │ │ tool-results/│ │ subagents/ │ │ MEMORY.md │ │ sessions/ │ │ tasks/ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 权限系统 │ │ Session存储 │ │ 沙箱执行 │ │ 规则持久化 │ │ .log.jsonl │ │ Shell/文件 │ └──────────────┘ └──────────────┘ └──────────────┘子系统与工作区的关系记忆日志层写入 memory/摘要层写入 MEMORY.md压缩大工具结果卸载到 tool-results/原始对话写入 sessions/子 Agent规格声明在 subagents/任务记录在 tasks/Session对话日志持久化在 agents//sessions/沙箱Shell 命令和文件操作的执行面由文件系统模式决定十、完整配置示例场景企业级差旅助手生产部署HarnessAgentagentHarnessAgent.builder().name(travel-assistant).model(newOpenAIChatModel(apiKey,gpt-4o))// 工作区所有状态的唯一事实来源.workspace(Path.of(/data/workspaces))// 文件系统Docker 沙箱隔离.filesystem(newDockerFilesystemSpec().image(python:3.11).build())// 状态持久化跨调用恢复.stateStore(newRedisAgentStateStore(redisClient))// 记忆双层长期记忆.memory(MemoryConfig.defaults())// 压缩防止上下文膨胀.compaction(CompactionConfig.builder().triggerMessages(40).keepMessages(10).build())// 大工具结果卸载.toolResultEviction(ToolResultEvictionConfig.defaults()).build();对应的工作区目录/data/workspaces/ └── travel-assistant/ ├── AGENTS.md ← 你是企业差旅助手... ├── MEMORY.md ← 用户张三偏好靠窗座位... ├── tools.json ← MCP: 航班API、酒店API ├── knowledge/ │ └── reimbursement.md ← 报销政策 ├── skills/ │ └── itinerary/SKILL.md ← 行程规划技能 ├── subagents/ │ ├── flight-agent.md ← 航班查询子Agent │ └── hotel-agent.md ← 酒店推荐子Agent ├── memory/ │ ├── 2026-08-10.md │ └── 2026-08-11.md └── agents/travel-assistant/ ├── sessions/ │ └── sess-001.log.jsonl └── tasks/ └── sess-001.json十一、设计哲学总结回顾 Workspace 的整套设计可以提炼出几个核心原则1. 文件即配置目录即架构不需要数据库、不需要配置中心、不需要 YAML 模板。一个目录结构就定义了 Agent 的全部行为。这是 Unix 哲学在 AI Agent 时代的回归。2. 逻辑与物理解耦Workspace 是逻辑抽象AbstractFilesystem 是物理实现。两者通过接口解耦使得同一套 Agent 逻辑可以在本机、沙箱、分布式存储之间无缝切换。3. 每轮重新拼装零停机更新System prompt 不是启动时生成一次的静态文本而是每轮推理前从工作区文件实时拼装。修改文件 修改行为无需重启。4. 约定优于配置目录名就是语义AGENTS.md 就是人格MEMORY.md 就是记忆skills/ 就是技能。不需要额外的注册机制或元数据描述。5. 人机共写工作区中的文件既由框架自动写入记忆、会话日志也由人类手动编辑人格、知识还由 Agent 自身修改自我进化。三方共存于同一个目录和谐共处。十二、与其他方案的对比维度传统配置中心数据库存储Workspace文件驱动可观测性需要查询接口需要 SQL/管理台直接打开文件版本管理部分支持困难天然 Git 友好非技术人员参与困难不可能编辑 Markdown 即可Agent 自我修改不支持复杂直接写文件多环境迁移需要导出/导入需要数据迁移复制目录分布式支持依赖配置中心天然支持通过 SharedStorage 支持安全隔离依赖平台依赖数据库权限Docker 沙箱原生支持十三、结语AgentScope Harness 的 Workspace 设计本质上回答了一个根本问题Agent 的自我应该存在于哪里答案是不在模型的权重里不在数据库的行里而在一个结构化的文件目录里。这个看似朴素的选择带来了可观测性、可版本化、可自我进化、可人机协作等一系列工程红利。当你把 Agent 看作一个有办公桌的员工而不是一个 API 端点时很多设计决策就变得自然而然了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进