一套代码,从个人助手走到企业级 Agent
过去一年,OpenClaw、Hermes、Claude Code 把 Harness Engineering 理念带进了主流视野。结构化工作区、上下文管理、工具约定——这些概念在单机上跑得很顺,但一到企业级场景,五个问题立刻暴露:
AgentScope Java 1.1.0 的 Harness Framework(入口类 HarnessAgent)就是解决这五个问题的。它不替换 ReAct 的推理循环,而是在关键时机插入 Hook,把工程答案打包进框架。
Harness 为每个 Agent 引入 workspace——一个结构化目录,承载全部持久化内容:
workspace/
├── AGENTS.md ← 人格与行为约定,每轮自动注入 system prompt
├── MEMORY.md ← 精炼长期记忆,后台周期性维护
├── knowledge/ ← 领域知识
├── skills/ ← 可复用技能,自动装配到工具集
├── subagents/ ← 子 Agent 规格声明
└── agents/<agentId>/
├── context/ ← 会话状态快照,进程重启后恢复
├── sessions/ ← 对话 JSONL
└── memory/ ← 每日记忆流水账
Workspace 不是临时缓存,是 Agent 的"大脑外化"。每次推理前自动加载,结束后自动回写,Agent 的能力随时间持续演化。
关键:人格、知识、技能、记忆全部沉淀在文件里,改一个文件等于升级一次 Agent,不需要重新编译部署。

Harness 核心架构图
本地磁盘目录在分布式场景下行不通。多个 Pod 各有一块本地盘,谁的 MEMORY.md 才是真的?
Harness 用 AbstractFilesystem 抽象层解决:
// 上层只关心统一接口
filesystem.read(path)
filesystem.write(path, content)
filesystem.execute(command) // 条件性注册
// 下层可适配任意后端
LocalFilesystem // 本机目录 + Shell
RemoteFilesystem // 远端 KV / 对象存储
SandboxFilesystem // 隔离沙箱
CompositeFilesystem // 混合路由

AbstractFilesystem 三种形态
核心:同一套 Agent 逻辑,切换 filesystem 配置即可在三种模式间迁移。
模式 | 数据落点 | Shell 执行 | 适用场景 |
|---|---|---|---|
Local + Shell | 本机目录 | 支持 | 个人开发、本地 Agent |
Remote 共享存储 | 远端 KV / OSS | 默认禁用 | 多副本在线 SaaS |
Sandbox 沙箱 | 隔离环境 | 沙箱内执行 | DataAgent、Coding Agent |
1. 工作区驱动的 Agent 运行环境
AGENTS.md 定义人格,skills/ 定义能力,knowledge/ 定义知识。每次 call() 前,WorkspaceContextHook 自动拼入 system prompt。
HarnessAgent agent = HarnessAgent.builder()
.name("my-agent")
.model(model)
.workspace(Paths.get(".agentscope/workspace"))
.compaction(CompactionConfig.builder()
.triggerMessages(50)
.keepMessages(20)
.build())
.build();
2. 双层记忆系统
第一层——每日流水账:每轮对话后,MemoryFlushHook 提炼新增事实,追加到 memory/YYYY-MM-DD.md。
第二层——长期记忆:后台 MemoryConsolidator 周期性合并、去重、精炼,输出 Token 预算内的 MEMORY.md,供每轮推理注入。
对话压缩:消息超限后自动压缩成摘要。若模型返回 context overflow,框架捕获异常、强制压缩、自动重试,对调用方透明。
3. 子 Agent 编排
子 Agent 有四种声明方式,推荐工作区文件驱动:
workspace/subagents/
├── data-analyst.md
├── code-reviewer.md
└── ...
调用分同步与异步:
// 同步
Msg result = agent.spawn("data-analyst", task).block();
// 异步
String taskId = agent.spawnAsync("code-reviewer", task);
Msg result = agent.taskOutput(taskId).block();
子 Agent 默认是"叶子"形态,不能无限递归,框架有最大深度兜底。
4. 沙箱状态可恢复
沙箱不只是隔离执行,更是多轮对话中隔离环境的连续性。每次 call() 结束,沙箱状态快照持久化;下次调用按 sessionId / userId 恢复。服务重启或请求漂移到其他节点,用户工作现场不丢失。
隔离粒度可选:SESSION(会话级)、USER(用户级)、GLOBAL(全局共享)。

从个人助手到企业级 Agent 演进路径
场景 A:个人代理 Agent(OpenClaw 类)
// 默认模式
HarnessAgent agent = HarnessAgent.builder()
.workspace(Paths.get("~/my-agent"))
.build();
单用户、本机运行、支持 Shell。工作区即配置,记忆自动沉淀,关闭再开状态可恢复。
场景 B:企业级数据服务(DataAgent)
HarnessAgent agent = HarnessAgent.builder()
.workspace(Paths.get("~/my-agent"))
.filesystem(new RemoteFilesystemSpec(redisStore))
.filesystem(new SandboxFilesystemSpec(sandboxClient))
.build();
多用户、多副本、沙箱隔离。长分析任务拆分子 Agent 并行,主 Agent 只协调汇总。
场景 C:企业在线服务(淘天交易 Agent 类)
HarnessAgent agent = HarnessAgent.builder()
.workspace(Paths.get("~/my-agent"))
.filesystem(new RemoteFilesystemSpec(ossStore))
.build();
// 只注册业务工具
agent.registerTool(new OrderQueryTool());
agent.registerTool(new PaymentTool());
不配置沙箱 = 不暴露 Shell 工具。安全边界由配置决定,不是开发者自律。多实例共享远端记忆,会话跨请求连续。
概念 | 一句话 | 解决什么问题 |
|---|---|---|
HarnessAgent | ReAct 的工程化封装入口 | 不想从零拼装压缩、记忆、会话、子任务 |
workspace | Agent 的工作目录,唯一事实来源 | 人格、知识、记忆、状态放哪、如何演化 |
filesystem | 文件读写统一接口 | 同一套逻辑如何在本地/远端/沙箱间切换 |
RuntimeContext | 单次 call() 的身份上下文 | 这一轮是谁、状态写到哪、多租户怎么隔离 |
sandbox | 隔离执行环境,状态可恢复 | 不信任输入下安全执行,并保持多轮连续 |
memory | 双层记忆:流水账 + 精炼长期记忆 | 长对话不丢事实、上下文不爆、历史可检索 |
总纲:HarnessAgent 负责编排,workspace 负责沉淀,filesystem 负责落点,RuntimeContext 负责身份,sandbox 负责边界,memory 负责长期演化。
AgentScope Java 1.1.0 把 Harness Engineering 里最难自己拼装的一组能力,收敛成了 HarnessAgent + 工作区约定 + 可插拔文件系统 + Hook 管线。
个人场景下,它是带记忆、带压缩、带子任务的加强版 ReAct Agent。 企业场景下,它是能把隔离、多租户、分布式记忆与子 Agent 编排变成配置项的基础设施。
如果你正在从个人助手原型演进到可上线的企业智能体,建议从 Harness 概览 跑通 Quick Start,再按 Filesystem 文档 选一种声明式模式,按需打开压缩、沙箱与子 Agent。
每一步都有文档与示例对照,不必从零发明一套"工作区即真理"的运行时。