Harness架构(Harness Engineering)是AI Agent(智能体)领域的一种工程基础设施参考框架。其核心公式为 Agent = Model + Harness,旨在通过一套系统化的工程方案,将基础大模型的原始智能转化为可靠、可控、可用的智能体能力。
第一章,Harness介绍
1. 研发背景与核心定义
在AI Agent开发中,单纯依赖基座模型(裸模型)面临无记忆、不能执行代码、知识过时、无工作环境等局限。Harness架构的诞生标志着AI工程实践从早期的"提示词工程"、"上下文工程"向构建完整智能体运行环境的重要演进。
如果将大模型比作一匹蓄势待发的"烈马",Harness就是人类牵引、驾驭这匹烈马的"缰绳"与"马具"。它不参与任务执行本身,但决定任务的方向、节奏与停止时机,解决的是"AI如何被约束"以及"AI如何稳定、合规、规模化地干活"的问题。
2. 核心组件
一个完整的Harness架构通常包含以下核心模块,为构建智能体系统提供技术骨架:
- System Prompt(系统提示词):贯穿所有组件的"神经系统",负责定义角色边界、注入领域知识、约束安全规则,并影响所有组件的工作方式。
- 文件系统与沙箱:提供工作空间、中间结果存储、版本追踪能力,并通过Bash沙箱赋予Agent代码执行、自我验证及安全隔离的能力。
- 记忆系统:通过文件存储和上下文注入,为模型提供长期记忆和知识扩展,避免每次对话都"从零开始"。
- 工具接入(Web Search + MCP):突破模型知识截止日期的限制,获取实时信息并连接外部工具与数据源。
- 上下文工程:管理模型的输入上下文,对抗"上下文腐烂",通过压缩、工具输出卸载、Skills渐进加载等策略优化信息呈现。
- 编排与验证(Hooks):协调多个Agent协同工作,并通过Hooks在关键节点注入确定性检查,以保障输出质量。
3. 计算机类比与三层区别
在计算机系统中,可以将Harness架构进行如下类比:模型是提供原始处理能力的CPU,上下文窗口是易失的工作内存(RAM),Agent Harness是负责整理上下文、提供标准驱动的执行基础设施(操作系统OS),而Agent则是运行在操作系统之上的具体应用逻辑(Application)。
在实际开发中,Harness与Framework(框架)、Agent存在明确的分层区别:
- Framework(如LangChain):是基础构建块,提供原语和工具,灵活但"裸露",需要开发者自行解决生产环境问题。
- Harness:是执行基础设施,提供有主观立场的默认架构(如上下文管理、状态持久化、验证机制),处理可靠执行的"怎么做"。
- Agent:是应用逻辑层,关注"做什么",即具体的目标、决策模式和领域逻辑。
4. 核心价值与行业趋势
Harness架构的本质是为企业级智能体构建一套"运行制度"和"控制闭环"。它通过定义目标与标准、递送上下文、智能体执行、验证与观察、追踪与学习五个环节,将原本由管理者凭经验完成的动作机械化、系统化,使AI系统能够自我校正与持续改进。
自2026年初由HashiCorp联合创始人Mitchell Hashimoto明确提出并命名以来,Harness Engineering迅速取代提示词工程,成为硅谷最流行的AI工程化范式,并受到OpenAI、Anthropic、LangChain等头部厂商的广泛实践与推动。
第二章 架构应用示例
为了让你更直观地理解Harness架构在实际项目中的落地,我们可以将核心组件的配置划分为**"工程约束层"和"运行时基础设施层"**两个维度。以下是基于主流企业级实践(如AgentScope Java Harness及Cow-Harness)梳理的配置示例:
一、 工程约束层:以文件系统为"唯一事实来源"
在实际落地中,Harness通常通过一个结构化的workspace(工作区)目录来承载所有约束。这相当于给AI设定了固定的"办公桌"和"操作手册"。
1. 核心目录结构配置
workspace/
├── AGENTS.md # 核心约束:定义Agent的人格、行为边界与协作规范
├── MEMORY.md # 长期记忆:精炼后的跨会话事实沉淀
├── knowledge/ # 领域知识:项目文档、API规范、架构设计等
├── skills/ # 可复用技能:封装好的工具或标准操作流程(SOP)
├── subagents/ # 子Agent规格:多Agent协作时的角色声明
└── agents/<agentId>/ # 运行时状态:会话历史、每日记忆流水账
**2. 关键文件配置示例(AGENTS.md)**这是Agent进入项目后的"第一份指南",配置内容通常包括:
- 项目架构约束:例如"必须遵循 Types → Config → Service → UI 的层级依赖模型"。
- 检索路径约定:遇到报错时,应该优先查阅哪些文档或日志。
- 安全与权限边界:明确禁止执行的危险操作(如直接rm -rf、访问未授权数据库等)。
二、 运行时基础设施层:抽象文件系统与沙箱
为了让同一套Agent逻辑能在个人开发、企业SaaS、安全隔离等不同场景下无缝切换,Harness通过AbstractFilesystem(抽象文件系统)进行底层配置。
1. 抽象文件系统模式配置上层Agent只需调用统一的 read/write/execute 接口,底层可根据环境切换三种形态:
- Local + Shell 模式:数据落点为本机目录,支持Shell执行。适用于个人开发和本地原型验证。
- Remote 共享存储模式:数据落点为远端KV或对象存储(OSS),默认禁用Shell。适用于多副本、多租户的在线SaaS服务。
- Sandbox 沙箱模式:数据与命令执行均在隔离环境内。适用于处理不受信任代码的Coding Agent或Data Agent。
2. 安全沙箱分级配置针对工具链与代码执行,Harness通常会配置分级隔离策略: - L1 进程级隔离:速度快,适用于受信任的内部工具调用。
- L2 容器隔离(Docker):行业标准,适用于大多数工具执行。
- L3 微虚拟机(Firecracker):适用于多租户或执行不受信任的代码。
- L4 完全虚拟机:最高安全性,适用于对隔离要求极高的敏感任务。
三、 自动化闭环配置:Hooks与软件过程改进
Harness不仅是静态约束,更是动态的"软件过程改进(SPI)"闭环。通过配置Hooks,将软件工程标准自动化:
- 上下文注入 Hook(WorkspaceContextHook):在每次推理前,自动将AGENTS.md、MEMORY.md等关键文件注入System Prompt,确保人格与知识不丢失。
- 记忆持久化 Hook(MemoryFlushHook):在对话结束后,自动提炼新事实写入记忆流水账,并周期性合并为精炼的长期记忆。
- 验证与评审门禁(Verification & Reviews):配置自动化Linter或"Agent-to-Agent Review"机制。例如,一个Agent负责生成代码,另一个Agent负责运行测试并审核结果,只有验证通过的产物才能进入下一阶段。
通过以上配置,Harness成功将"下一轮怎么办、上下文爆了怎么办、状态丢了怎么办"等工程难题打包解决,让开发者能够专注于Agent的业务逻辑本身。
第三章,代码审查Agent示例
下面是一个基于 AgentScope Java Harness 的最小可运行 Demo,它将你之前了解到的 workspace、AGENTS.md、AbstractFilesystem 等核心概念全部落地。
这个 Demo 的目标是:构建一个能进行多轮对话、自动持久化记忆、且具备明确安全边界的 Agent。
🛠️ 第一步:准备项目与依赖
- 创建一个标准的 Maven 项目。
- 在 pom.xml 中引入 Harness 核心依赖。这里以 2.0 版本为例,它提供了 HarnessAgent 这个一站式入口。
XML
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-harness</artifactId>
<version>2.0.0-RC2</version>
</dependency>
📁 第二步:创建结构化 Workspace
在项目根目录下创建一个 workspace 文件夹,并在其中创建 AGENTS.md 文件。这是 Harness 的核心,Agent 的所有人格、知识和约束都源于此。
workspace/AGENTS.md 内容示例:
XML
# Agent 角色定义
你是一个专业的代码审查助手。
# 行为约束
1. 只审查用户提供的 Java 代码片段。
2. 指出潜在的性能问题和空指针风险。
3. 禁止执行任何 Shell 命令或访问外部网络。
4. 如果用户要求执行危险操作,请礼貌拒绝并说明原因。
# 审查标准
- 遵循 Clean Code 原则
- 优先保证代码可读性
💻 第三步:编写核心启动代码
创建一个 Application.java 作为入口。这段代码展示了如何构建 HarnessAgent 并配置运行时上下文,实现会话持久化和安全隔离。
java
import io.agentscope.harness.HarnessAgent;
import io.agentscope.harness.RuntimeContext;
import io.agentscope.harness.compaction.CompactionConfig;
import io.agentscope.message.Msg;
import java.nio.file.Paths;
public class Application {
public static void main(String[] args) {
// 1. 构建 HarnessAgent
HarnessAgent agent = HarnessAgent.builder()
.name("code-reviewer")
// 配置你的 LLM 模型 (此处以 DeepSeek 为例)
.model(modelConfig -> modelConfig
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.modelName("deepseek-chat")
.baseUrl("https://api.deepseek.com")
)
// 指向我们刚创建的 workspace
.workspace(Paths.get("workspace"))
// 配置上下文压缩,防止 token 溢出
.compaction(CompactionConfig.builder()
.triggerMessages(50) // 消息数超过50条时触发压缩
.keepMessages(20) // 压缩后保留最近20条
.build()
)
.build();
// 2. 创建运行时上下文,实现多轮对话与用户隔离
RuntimeContext ctx = RuntimeContext.builder()
.sessionId("session-001") // 相同 sessionId 自动续接上下文
.userId("developer-alice") // 多用户场景必传,用于命名空间隔离
.build();
// 3. 与 Agent 进行多轮对话
Msg userMsg1 = Msg.builder().textContent("请审查这段代码: String s = null; s.length();").build();
Msg reply1 = agent.call(userMsg1, ctx).block();
System.out.println("Agent 回复: " + reply1.getTextContent());
// 第二次调用,Agent 能记住上文的审查标准
Msg userMsg2 = Msg.builder().textContent("如果我想优化它,应该怎么做?").build();
Msg reply2 = agent.call(userMsg2, ctx).block();
System.out.println("Agent 回复: " + reply2.getTextContent());
}
}
🚀 第四步:运行与验证
- 设置环境变量 DEEPSEEK_API_KEY 为你的 API 密钥。
- 运行 Application.java。
- 关键验证点 :运行结束后,检查 workspace 目录。你会看到自动生成了 memory/ 和 agents// 等文件夹。这说明 Agent 已经成功将对话历史和记忆持久化到了文件系统中,实现了"大脑外化"。下次启动时,只要 sessionId 和 userId 不变,Agent 就能无缝接续上次的对话状态。
💡 Demo 核心亮点解析
|---------------------|---------------|------------------------------------------------------------------------|
| 配置项 | 对应 Harness 概念 | 解决的问题 |
| workspace/AGENTS.md | 工程约束层 | 将 Agent 的人格、安全规则、领域知识从代码中解耦,实现"修改文件即升级 Agent"。 |
| AbstractFilesystem | 运行时基础设施 | 代码中虽未显式配置,但 Harness 默认使用本地文件系统。在生产环境中,只需切换配置即可无缝迁移到远端存储或沙箱模式,无需修改业务代码。 |
| RuntimeContext | 会话与记忆管理 | 通过 sessionId 和 userId 实现多轮对话的上下文自动恢复和多租户隔离,解决了"状态丢失"和"用户混淆"的工程难题。 |
| CompactionConfig | 上下文工程 | 主动管理模型输入窗口,避免因对话过长导致的上下文溢出和性能下降。 |
这个 Demo 已经是一个具备生产级雏形的 Agent 应用。你可以在此基础上,通过修改 AGENTS.md 来调整 Agent 能力,或通过更换 filesystem 配置来适配不同的部署环境,真正体验 Harness 架构带来的工程化便利。
第四章 多Agent协作流水线
我们将之前的单点代码审查扩展为一个**"代码审查 + 自动修复"的多 Agent 协作流水线** 。
在 Harness 架构中,多 Agent 协作的核心在于结构化分工 与上下文无缝传递 。我们将引入两个角色:
- Reviewer Agent(审查员) :负责发现问题,输出结构化报告。
- Fixer Agent(修复员) :负责根据审查报告,输出修复后的代码。
以下是扩展后的最小 Demo 落地方案:
🛠️ 第一步:扩展 Workspace 结构
我们需要为两个 Agent 分别定义约束,并创建一个共享的"上下文传递协议"。
java
workspace/
├── AGENTS.md # 全局系统提示词(定义协作流程)
├── reviewer/ # Reviewer 专属目录
│ └── AGENTS.md # 审查员人格与输出规范
└── fixer/ # Fixer 专属目录
└── AGENTS.md # 修复员人格与代码规范
1. 全局系统提示词 workspace/AGENTS.md
java
# 协作流程
本系统由两个 Agent 组成:
1. Reviewer:审查代码,输出结构化问题列表。
2. Fixer:根据 Reviewer 的输出,生成修复后的完整代码。
# 上下文传递协议
Reviewer 的输出必须包含以下 JSON 结构,Fixer 将直接解析此结构:
{
"issues": [{"line": 1, "type": "NPE", "description": "..."}],
"original_code": "..."
}
2. Reviewer 专属约束 workspace/reviewer/AGENTS.md
java
# 角色
你是代码审查专家。
# 输出规范
必须输出 JSON 格式,包含 issues 数组和 original_code。
禁止输出任何解释性文字,只输出 JSON。
3. Fixer 专属约束 workspace/fixer/AGENTS.md
java
# 角色
你是代码修复专家。
# 输入
你将收到一个 JSON,包含 issues 和 original_code。
# 输出规范
只输出修复后的完整 Java 代码,不要包含 markdown 代码块标记,不要包含任何解释。
💻 第二步:编写多 Agent 协作核心代码
java
import io.agentscope.harness.HarnessAgent;
import io.agentscope.harness.RuntimeContext;
import io.agentscope.harness.compaction.CompactionConfig;
import io.agentscope.message.Msg;
import java.nio.file.Paths;
public class MultiAgentDemo {
public static void main(String[] args) {
// 1. 构建 Reviewer Agent
HarnessAgent reviewer = HarnessAgent.builder()
.name("reviewer")
.model(modelConfig -> modelConfig
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.modelName("deepseek-chat")
.baseUrl("https://api.deepseek.com")
)
.workspace(Paths.get("workspace/reviewer")) // 专属 workspace
.compaction(CompactionConfig.builder().triggerMessages(50).keepMessages(20).build())
.build();
// 2. 构建 Fixer Agent
HarnessAgent fixer = HarnessAgent.builder()
.name("fixer")
.model(modelConfig -> modelConfig
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.modelName("deepseek-chat")
.baseUrl("https://api.deepseek.com")
)
.workspace(Paths.get("workspace/fixer")) // 专属 workspace
.compaction(CompactionConfig.builder().triggerMessages(50).keepMessages(20).build())
.build();
// 3. 协作流水线
String originalCode = "String s = null; s.length();";
RuntimeContext ctx = RuntimeContext.builder()
.sessionId("collab-session-001")
.userId("developer-alice")
.build();
// 第一步:Reviewer 审查
System.out.println("=== Reviewer 开始审查 ===");
Msg reviewRequest = Msg.builder().textContent("请审查: " + originalCode).build();
Msg reviewResult = reviewer.call(reviewRequest, ctx).block();
String reviewJson = reviewResult.getTextContent();
System.out.println("Reviewer 输出: " + reviewJson);
// 第二步:Fixer 修复(直接传递 Reviewer 的 JSON 输出)
System.out.println("\n=== Fixer 开始修复 ===");
Msg fixRequest = Msg.builder().textContent("请修复以下问题: " + reviewJson).build();
Msg fixResult = fixer.call(fixRequest, ctx).block();
String fixedCode = fixResult.getTextContent();
System.out.println("Fixer 输出: " + fixedCode);
// 第三步:可选 - 让 Reviewer 再次验证修复结果
System.out.println("\n=== Reviewer 二次验证 ===");
Msg verifyRequest = Msg.builder().textContent("请验证修复后的代码是否解决了问题: " + fixedCode).build();
Msg verifyResult = reviewer.call(verifyRequest, ctx).block();
System.out.println("验证结果: " + verifyResult.getTextContent());
}
}
🚀 第三步:运行与验证
- 设置环境变量 DEEPSEEK_API_KEY。
- 运行 MultiAgentDemo.java。
- 关键验证点 :
- Reviewer 输出的是纯 JSON ,没有多余的解释文字。
- Fixer 接收 JSON 后,输出的是纯代码 ,没有 markdown 标记。
- 两个 Agent 的 workspace 目录下分别生成了独立的记忆文件,实现了状态隔离 。
- 整个协作流程是确定性的 ,JSON 作为上下文传递协议,避免了自然语言传递的歧义。
💡 多 Agent 协作核心亮点解析
|-----------------------|---------------|------------------------------------------------|
| 配置项 | 对应 Harness 概念 | 解决的问题 |
| 独立 workspace | 工程约束层 | 每个 Agent 有专属的人格和约束,避免角色混淆。 |
| JSON 传递协议 | 上下文工程 | 用结构化数据替代自然语言传递,确保下游 Agent 能精准解析上游输出。 |
| 独立 RuntimeContext | 会话管理 | 两个 Agent 共享同一个 sessionId ,但各自维护独立的记忆文件,既协作又隔离。 |
| 二次验证闭环 | 验证与评审门禁 | Fixer 修复后,Reviewer 再次验证,形成"审查→修复→验证"的自动化闭环。 |
📌 进阶:如何扩展到更复杂的协作场景?
如果你需要更多 Agent(如测试 Agent、文档 Agent),只需:
- 在 workspace/ 下创建新的专属目录(如 tester/AGENTS.md)。
- 定义新的 JSON 传递协议。
- 在代码中按流水线顺序调用即可。
Harness 架构的精髓在于:Agent 是"插件",workspace 是"插槽",JSON 是"接口" 。只要协议定义清晰,你可以像搭积木一样无限扩展协作场景。
第五章 Agent协作逻辑工程化
将多 Agent 协作逻辑封装为工具类,是 Harness 架构迈向工程化、模块化的关键一步。
下面我为你封装了一个通用的 AgentPipeline 工具类。它采用了**"配置即代码"**的设计思路,将 Agent 的初始化、上下文传递和流水线执行全部抽象出来。以后你只需要定义好每个节点的 workspace 和传递协议,就可以像搭积木一样随意扩展流水线。
💻 核心工具类:AgentPipeline.java
java
import io.agentscope.harness.HarnessAgent;
import io.agentscope.harness.RuntimeContext;
import io.agentscope.harness.compaction.CompactionConfig;
import io.agentscope.message.Msg;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
/**
* 多 Agent 协作流水线封装工具类
*/
public class AgentPipeline {
// 定义流水线中的单个节点
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PipelineNode {
private String name; // 节点名称(对应 workspace 目录)
private String promptTemplate; // 提示词模板(用于动态注入上游输出)
private HarnessAgent agent; // 实际执行的 Agent 实例
}
private final List<PipelineNode> nodes;
private final RuntimeContext context;
public AgentPipeline(RuntimeContext context) {
this.nodes = new ArrayList<>();
this.context = context;
}
/**
* 向流水线中添加一个 Agent 节点
* @param workspacePath 该 Agent 专属的 workspace 路径
* @param promptTemplate 提示词模板,使用 {input} 占位符接收上游输出
*/
public AgentPipeline addNode(Path workspacePath, String promptTemplate, String name) {
HarnessAgent agent = HarnessAgent.builder()
.name(name)
.model(modelConfig -> modelConfig
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.modelName("deepseek-chat")
.baseUrl("https://api.deepseek.com")
)
.workspace(workspacePath)
.compaction(CompactionConfig.builder()
.triggerMessages(50)
.keepMessages(20)
.build())
.build();
nodes.add(new PipelineNode(name, promptTemplate, agent));
return this; // 支持链式调用
}
/**
* 执行流水线
* @param initialInput 流水线的初始输入
* @return 最后一个节点的输出结果
*/
public String execute(String initialInput) {
String currentInput = initialInput;
for (PipelineNode node : nodes) {
System.out.println(">>> 正在执行节点: " + node.getName());
// 将上游输出动态注入提示词模板
String finalPrompt = node.getPromptTemplate().replace("{input}", currentInput);
Msg request = Msg.builder().textContent(finalPrompt).build();
Msg response = node.getAgent().call(request, context).block();
currentInput = response.getTextContent(); // 将当前输出作为下一节点的输入
}
return currentInput;
}
}
🚀 使用示例:一键重构多 Agent 协作
有了这个工具类,原来的 MultiAgentDemo 可以被极度简化。我们只需要关注"业务逻辑"(节点定义和协议),而不再需要关心底层的 API 调用。
java
import java.nio.file.Paths;
public class PipelineDemo {
public static void main(String[] args) {
// 1. 准备共享的运行时上下文
RuntimeContext ctx = RuntimeContext.builder()
.sessionId("collab-session-001")
.userId("developer-alice")
.build();
// 2. 定义流水线(链式调用,清晰直观)
AgentPipeline pipeline = new AgentPipeline(ctx)
// 添加审查节点
.addNode(
Paths.get("workspace/reviewer"),
"请审查以下代码并输出JSON格式的问题列表: {input}",
"reviewer"
)
// 添加修复节点(直接接收上游的 JSON 输出)
.addNode(
Paths.get("workspace/fixer"),
"请根据以下审查报告修复代码,只输出纯代码: {input}",
"fixer"
);
// 3. 一键执行
String originalCode = "String s = null; s.length();";
String finalResult = pipeline.execute(originalCode);
System.out.println("\n=== 流水线最终输出 ===");
System.out.println(finalResult);
}
}
💡 封装后的架构优势
- 高度解耦:业务开发人员完全不需要知道 HarnessAgent 是如何构建的,也不需要关心 call() 方法的底层实现。他们只需要定义好 workspace 目录和提示词模板。
- 协议标准化:通过 {input} 占位符,我们强制定义了上下游之间的数据传递契约。如果下游需要 JSON,上游的 AGENTS.md 就必须约束输出 JSON。
- 无限扩展性:如果未来需要增加一个"测试节点"或"文档生成节点",只需要在 addNode 链式调用中再加一行代码即可,完全符合开闭原则(对扩展开放,对修改关闭)。
这套封装完美体现了 Harness 架构中"把工程难题打包解决"的理念。你觉得这个工具类的设计符合你的预期吗?如果需要,我们可以继续探讨如何在这个流水线中加入"人工审批(Human-in-the-loop)"的断点机制。