Skip to content

Repository files navigation

Java Harness Framework

为 AI Agent 时代构建的 Java 驾驭工程框架

核心公式:Agent = Model + Harness

模型提供原始智能,Harness 让这个智能能够真正投入生产。


目录


背景与动机

Harness Engineering 是什么?

2026 年初,AI 工程领域迎来范式转变。HashiCorp 联合创始人 Mitchell Hashimoto 正式提出 Harness Engineering(驾驭工程),随后 OpenAI 与 Anthropic 几乎同步发布了各自的 Harness 实践文章。

核心公式来自 LangChain 工程师 Vivek Trivedy:

Agent = Model + Harness

更进一步的推导:

Harness = (功能侧架构 + 治理侧架构) - 模型层

这意味着:除了模型本身,所有让 AI 在企业级场景中稳定运行的工程设施,都属于 Harness 的范畴

工程范式三次迁移

阶段 关注点 核心问题
Prompt Engineering 说什么 如何让模型输出更准确
Context Engineering 给什么上下文 如何管理模型的信息输入
Harness Engineering 在什么条件下运行 如何让模型可靠地长期工作

Harness 解决的三个核心问题

迷失问题(Doom Loop):Agent 在复杂任务中失去方向,反复犯同样的错误,耗费大量 token 却无进展。

熵增问题(Entropy):随着 AI 持续生成代码,架构腐化、文档过时、命名混乱,系统质量持续下滑。

信任问题(Trust):AI 生成代码的质量、安全性、合规性无法被系统化保证,只能靠人工逐行审查。

Anthropic 官方 Harness 的三个设计模式

Anthropic 在 Claude Managed Agents 中总结了三个关键设计模式,本框架也遵循这些原则:

模式一:使用模型已知的工具 提供 Claude 已经精通的通用工具(如 bash、文件读写),让模型自己组合出解决方案,而非为每个任务设计专用工具。Claude 会随着模型迭代不断提升这些工具的使用能力。

模式二:让模型自主决策编排 通过代码执行工具,让 Agent 自己决定哪些工具结果需要处理、哪些可以过滤、哪些可以管道传输。编排决策从 Harness 转移到模型本身,只有最终输出进入上下文窗口,大幅降低 token 消耗。

模式三:谨慎设置边界 需要安全边界的操作才提升为专用工具——可逆性是好标准,难以逆转的操作(外部 API 调用、文件写入)通过专用工具加拦截钩子控制。边界设置应持续重新评估。

架构范式:从"宠物"到"牲畜"

旧架构("宠物") 新架构("牲畜")
大脑/双手/记忆全部打包在黑盒里 无状态化设计,组件解耦
故障黑箱化,难以调试 反脆弱,单点故障不影响整体
难以规模化 从 1 个 Agent 到 1000 个,只是数字变化

Java 生态的天然优势

Java 的"Ambient Affordances"(环境自生能力)天然适合构建生产级 Harness:

  • 强类型系统:编译期约束,架构违规即时暴露
  • ArchUnit:Java 架构约束测试的事实标准
  • Spring 生态:依赖注入、AOP、事件驱动,天然支持横切关注点
  • Project Reactor:响应式编程,非阻塞执行,天然匹配 Agent 的异步特性
  • OpenTelemetry Java:成熟的自动插桩方案

核心概念

Harness 的六大组件

一个完整的 Harness 必须包含以下六大工程化组件:

组件 职责 类比
Tool Integration MCP 网关、Skills 编排、工具统一抽象 给模型"双手"
Memory & State 短期上下文、长期记忆、断点续传 给模型"记忆"
Context Engineering 动态 Prompt 策展、技能渐进披露 给模型"领域经验"
Planning & Decompose 任务拆解、ReAct 循环、自我验证 给模型"规划能力"
AI Safety 沙箱隔离、验证钩子、自我纠正循环 给模型"安全边界"
Extensions 微内核 + 插件化,MCP/Skills/记忆扩展 给模型"可扩展能力"

Agent 执行闭环

while (!taskComplete) {
    context  = gather();     // 收集上下文(渐进式披露)
    action   = decide();     // ReAct 推理决策
    result   = execute();    // 工具执行(沙箱化)
    verified = verify();     // 多维度验证
    update(result, verified); // 更新状态 + 记忆
}

框架层坍缩趋势

随着模型能力增强,传统 AI 框架正在发生重构:

  • 80% 的能力迁移到模型层:定义 Agent、消息路由、生命周期管理,大模型已原生支持
  • 20% 的能力沉淀为 Harness:持久化、确定性重放、成本控制、可观测性、错误恢复

结论:未来 AI 应用开发,可能不再需要重型编排框架,但一定需要 Harness 层来治理运行时。


技术选型

核心依赖

层级 技术选型 版本 选型理由
Agent 核心 agentscope-java 1.0.11+ 生产级 Java Agent 框架,原生 ReAct、工具调用、响应式架构
可观测性 Langfuse via OTLP v3.22+ 专为 LLM 设计的可观测平台,支持 Trace/Generation/Evaluation
链路追踪 OpenTelemetry Java 1.x agentscope-java 已内置,直接对接 Langfuse OTLP 端点
响应式 Project Reactor 3.x agentscope-java 底层,非阻塞执行
架构约束 ArchUnit 1.x Java 架构测试事实标准
应用框架 Spring Boot 3.x 3.x 可选,agentscope 提供 Spring Boot Starter
工具协议 MCP (Model Context Protocol) - agentscope-java 原生支持

为什么选 agentscope-java?

agentscope-java 提供了 Harness 所需的全部 Agent 核心能力,无需重复造轮子:

  • ReAct 推理引擎:动态决策工具调用,比 rigid workflow 更灵活
  • 运行时介入机制:安全中断、优雅取消、人机协同(Hook 系统)
  • PlanNotebook:结构化任务管理,将复杂目标分解为可追踪步骤
  • 结构化输出:自纠错解析器,LLM 输出直接映射到 Java POJO
  • 长期记忆:跨会话持久化,支持语义搜索,多租户隔离
  • 原生 OTel 支持:内置 OpenTelemetry 链路追踪,直接对接 Langfuse
  • 响应式架构:基于 Project Reactor,GraalVM 原生编译支持 200ms 冷启动

为什么选 Langfuse?

  • 专为 LLM 设计:Trace → Span → Generation 三层模型,完美匹配 Agent 执行结构
  • OTLP 原生支持:agentscope-java 的 OTel traces 可直接打到 Langfuse OTLP 端点,零额外代码
  • Evaluation 体系:内置 LLM-as-Judge、人工标注、自动化评估流水线
  • Prompt Management:版本化 Prompt 管理,生产环境动态更新
  • 开源可自托管:数据不出境,满足企业合规要求

整体架构

┌──────────────────────────────────────────────────────────────────┐
│                     Java Harness Framework                        │
│                                                                    │
│  ┌───────────────────────────────────────────────────────────┐   │
│  │                   HarnessOrchestrator                      │   │
│  │            (任务规划 · Sprint 管理 · 并行控制)             │   │
│  └────────────────────────────┬──────────────────────────────┘   │
│                                │                                    │
│  ┌─────────────────────────────┼────────────────────────────┐     │
│  │          agentscope-java (Agent 核心)                     │     │
│  │                             │                              │     │
│  │  ReActAgent ─── Toolkit ─── Memory ─── PlanNotebook      │     │
│  │       │             │           │                          │     │
│  │  Hook System    MCP Bridge  LongTermMemory                │     │
│  └─────────────────────────────┬────────────────────────────┘     │
│                                 │ OTel Traces                       │
│  Harness 治理层                 │                                    │
│  ┌──────────────┐  ┌───────────▼──────┐  ┌───────────────────┐   │
│  │ContextEngine │  │  VerifyPipeline   │  │   EntropyAgent    │   │
│  └──────────────┘  └──────────────────┘  └───────────────────┘   │
│  ┌──────────────┐  ┌──────────────────┐  ┌───────────────────┐   │
│  │ConstraintGuard  │  SafetyBoundary  │  │    StateStore     │   │
│  └──────────────┘  └──────────────────┘  └───────────────────┘   │
│                                 │ OTLP/HTTP                         │
│  ┌──────────────────────────────▼───────────────────────────┐     │
│  │                  Langfuse (可观测层)                       │     │
│  │   Traces · Generations · Evaluations · Prompt Management  │     │
│  └───────────────────────────────────────────────────────────┘     │
└──────────────────────────────────────────────────────────────────┘

六层 Harness 设计

┌──────────────────────────────────────────────────────┐
│  L6  安全边界层  (Safety Boundary)                    │
│       红线规则 · 权限白名单 · 熔断降级 · 一键回滚     │
├──────────────────────────────────────────────────────┤
│  L5  验证反馈层  (Verification & Feedback)            │
│       ArchUnit · 单元测试 · E2E 验证 · LLM 评分      │
├──────────────────────────────────────────────────────┤
│  L4  状态记忆层  (State & Memory)                     │
│       Session 管理 · LongTermMemory · 断点续传        │
├──────────────────────────────────────────────────────┤
│  L3  执行流程层  (Execution & Workflow)               │
│       PlanNotebook · Sprint 调度 · 并行 Agent 控制    │
├──────────────────────────────────────────────────────┤
│  L2  工具能力层  (Tools & Skills)                     │
│       Toolkit · MCP Bridge · Skills · 沙箱执行        │
├──────────────────────────────────────────────────────┤
│  L1  上下文信息层  (Context & Knowledge)              │
│       AGENTS.md · 架构文档 · Skills YAML · 动态上下文 │
└──────────────────────────────────────────────────────┘
            ↕ agentscope-java ReActAgent
层级 类比 核心职责 主要实现
L1 上下文信息层 岗位说明书 知识供给、渐进式披露 ContextEngine + AGENTS.md
L2 工具能力层 工具箱 原子化工具、MCP 集成 agentscope Toolkit + MCP
L3 执行流程层 标准流程 任务拆解、Sprint 执行 PlanNotebook + Orchestrator
L4 状态记忆层 项目笔记本 跨窗口记忆、会话持久化 agentscope Session + LongTermMemory
L5 验证反馈层 质检流程 约束验证、自动测试 VerifyPipeline + ArchUnit
L6 安全边界层 红线规则 权限控制、应急兜底 SafetyBoundary + Hook

三大工程支柱

支柱一:上下文工程(Context Engineering)

地图模式 vs 说明书模式

❌ 说明书模式:一个 1000 行 AGENTS.md,塞入所有规则 → 挤占上下文,成为"陈旧规则的坟场"
✅ 地图模式:100 行 AGENTS.md 作为目录 + docs/ 深层文档按需加载(渐进式披露)

agentscope-java 的 Skills 机制天然支持渐进式披露:每个 Skill 的 YAML 前言预加载到上下文(简短描述),需要时通过文件读取工具展开完整内容。

// ContextEngine:按 token 预算动态装配上下文
@Service
public class ContextEngine {

    // Skills 渐进式披露:只预加载摘要,按需展开详情
    public String buildSystemPrompt(Task task) {
        StringBuilder sb = new StringBuilder();
        sb.append(loadAgentsMd());                          // 核心地图,~100 tokens
        sb.append(loadSkillSummaries(task.getCategory())); // Skills 摘要,供 Agent 判断是否需要展开
        return sb.toString();
    }
}

支柱二:架构约束(Architectural Constraints)

原则:将「代码品味」硬编码为机械规则,错误消息必须包含修复指令

// ArchUnit 强制分层依赖
@AnalyzeClasses(packages = "com.example")
public class ArchitectureConstraintTest {

    @ArchTest
    static final ArchRule LAYER_DEPENDENCY =
        layeredArchitecture()
            .layer("Types").definedBy("..types..")
            .layer("Config").definedBy("..config..")
            .layer("Repository").definedBy("..repository..")
            .layer("Service").definedBy("..service..")
            .layer("Runtime").definedBy("..runtime..")
            .layer("Controller").definedBy("..controller..")
            .whereLayer("Service").mayNotAccessLayers("Controller")
            .whereLayer("Repository").mayNotAccessLayers("Service", "Controller");

    // 违规时报错:
    // [ARCH-001] Service 层不能直接依赖 Controller 层
    // ❌ 问题:UserService 引用了 UserController
    // ✅ 修复:将共享逻辑提取到 Types 层或独立的 DTO 类
    // 📖 文档:docs/architecture/boundaries.md#layer-rules
}

支柱三:熵管理(Entropy Management)

原则:定期运行「垃圾回收」Agent,对抗架构腐化,生成重构 PR 而非直接修改

@Scheduled(cron = "0 0 2 * * MON")
@Component
public class EntropyAgent {

    @Autowired
    private ReActAgent refactorAgent;  // agentscope-java ReActAgent

    public void collect() {
        EntropyReport report = scanner.scan();

        // 用 Agent 生成重构建议,生成 PR 而非直接修改
        // 保持人类对架构决策的最终控制权
        if (report.getDriftScore() > threshold) {
            refactorAgent.call(buildRefactorPrompt(report))
                .flatMap(result -> gitService.createPR(result))
                .subscribe();
        }
    }
}

核心组件详解

HarnessOrchestrator — Planner-Generator-Evaluator 三角架构

基于 agentscope-java 的 PlanNotebook,实现 Anthropic 2026 年实践中的三智能体架构:

@Service
public class HarnessOrchestrator {

    @Autowired private ReActAgent plannerAgent;    // 规划者
    @Autowired private ReActAgent generatorAgent;  // 执行者
    @Autowired private ReActAgent evaluatorAgent;  // 评估者

    public Mono<ExecutionReport> execute(String taskDescription) {
        return plannerAgent
            .call(buildPlannerPrompt(taskDescription))
            .flatMap(plan -> {
                List<Feature> features = parseFeatures(plan);
                // 所有功能初始标记 FAILING(TDD 思想)
                features.forEach(f -> f.setStatus(FeatureStatus.FAILING));
                stateStore.save(features);

                return Flux.fromIterable(features)
                    .concatMap(this::executeFeatureSprint)
                    .collectList()
                    .map(ExecutionReport::new);
            });
    }

    private Mono<SprintResult> executeFeatureSprint(Feature feature) {
        return Mono.defer(() -> {
            if (loopDetector.isLoop(feature)) {
                return Mono.just(SprintResult.escalate(feature));
            }

            Context ctx = contextEngine.buildContext(feature.toTask());

            return generatorAgent.call(ctx.toMsg())
                .flatMap(action -> verifyPipeline.verify(action)
                    .flatMap(verify -> {
                        if (verify.isPassing()) {
                            feature.setStatus(FeatureStatus.PASSING);
                            // 每个 Sprint 后立即 commit,保留可接班产物
                            return gitService.commit("feat: " + feature.getName())
                                .thenReturn(SprintResult.success(feature));
                        }
                        feature.addFeedback(verify.getReport());
                        return executeFeatureSprint(feature);  // 带反馈重试
                    }));
        });
    }
}

VerifyPipeline — 验证反馈闭环

@Component
public class VerifyPipeline {

    public Mono<VerifyResult> verify(Msg agentOutput) {
        return Mono.zip(
            Mono.fromCallable(() -> compiler.check(agentOutput)),         // 编译检查
            Mono.fromCallable(() -> constraintGuard.validate(agentOutput)), // ArchUnit
            testRunner.runTests(agentOutput.getTargetModule()),             // 单元测试
            evaluatorAgent.call(buildEvalPrompt(agentOutput))               // LLM 评分
        ).map(tuple -> VerifyResult.aggregate(
            tuple.getT1(), tuple.getT2(), tuple.getT3(), tuple.getT4()
        ));
    }
}

LoopDetector — Doom Loop 防护

@Component
public class LoopDetector {

    public boolean isLoop(Feature feature) {
        List<String> recentErrors = feature.getRecentErrors(5);
        if (recentErrors.size() < 5) return false;

        long uniqueTypes = recentErrors.stream().distinct().count();
        if (uniqueTypes <= 1) {
            // 5 次内错误类型少于 2 种,判定为 Doom Loop,触发人工介入
            notificationService.escalate(
                "Doom Loop 检测:[" + feature.getName() + "] 需要人工介入"
            );
            return true;
        }
        return false;
    }
}

项目结构

java-harness-framework/
├── harness-core/                          # Harness 核心调度层
│   └── src/main/java/com/harness/
│       ├── orchestrator/
│       │   ├── HarnessOrchestrator.java   # Planner-Generator-Evaluator 调度
│       │   ├── SprintManager.java
│       │   └── LoopDetector.java
│       ├── context/
│       │   ├── ContextEngine.java         # 上下文装配(地图模式)
│       │   └── DocumentLoader.java
│       └── model/
│           ├── Feature.java
│           ├── SprintResult.java
│           └── ExecutionReport.java
│
├── harness-agent/                         # Agent 核心层(agentscope-java 集成)
│   ├── pom.xml                            # 依赖 io.agentscope:agentscope:1.0.11
│   └── src/main/java/com/harness/agent/
│       ├── config/
│       │   └── AgentScopeConfig.java      # Planner/Generator/Evaluator Bean 配置
│       ├── tools/
│       │   ├── HarnessToolkit.java        # 工具集注册(含 MCP Bridge)
│       │   ├── FileReadTool.java
│       │   ├── FileWriteTool.java
│       │   └── ShellExecuteTool.java      # 沙箱化 Shell
│       ├── hooks/
│       │   ├── SafetyHook.java            # 安全边界钩子(L6)
│       │   ├── ConstraintHook.java        # 架构约束钩子(L5)
│       │   └── AuditHook.java             # 审计日志
│       └── memory/
│           └── HarnessMemoryConfig.java
│
├── harness-observability/                 # 可观测性层(Langfuse via OTLP)
│   ├── pom.xml
│   └── src/main/java/com/harness/observability/
│       ├── config/
│       │   └── LangfuseOtelConfig.java    # OTLP → Langfuse 端点配置
│       ├── instrument/
│       │   ├── HarnessSpanDecorator.java  # gen_ai.* 语义属性注入
│       │   └── GenAiAttributes.java       # OTel 属性常量定义
│       └── evaluation/
│           └── LangfuseEvalClient.java    # 评分回写 Langfuse API
│
├── harness-constraints/                   # 架构约束层(ArchUnit)
│   ├── src/test/java/com/harness/
│   │   └── ArchitectureConstraintTest.java
│   └── config/checkstyle.xml
│
├── harness-verify/                        # 验证反馈层
│   └── src/main/java/com/harness/verify/
│       ├── VerifyPipeline.java
│       └── TestRunner.java
│
├── harness-entropy/                       # 熵管理层
│   └── src/main/java/com/harness/entropy/
│       ├── EntropyAgent.java
│       ├── EntropyScanner.java
│       └── RefactorPRGenerator.java
│
├── harness-spring-boot-starter/           # Spring Boot 自动配置
│   └── src/main/java/com/harness/autoconfigure/
│       ├── HarnessAutoConfiguration.java
│       └── HarnessProperties.java
│
├── harness-examples/
│   ├── coding-agent-demo/
│   ├── multi-agent-pipeline/
│   └── enterprise-integration/
│
├── docs/
│   ├── architecture/
│   │   ├── overview.md
│   │   ├── boundaries.md                  # 模块边界 + 约束错误消息模板
│   │   └── adr/
│   ├── conventions/
│   │   ├── coding-style.md
│   │   └── testing.md
│   └── plans/current-sprint.md
│
├── AGENTS.md                              # Agent 导航地图(≤100 行)
└── pom.xml

AgentScope-Java 集成

Maven 依赖

<!-- harness-agent/pom.xml -->
<dependencies>
    <!-- AgentScope Java 全量包(含 MCP SDK、OTel 依赖) -->
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope</artifactId>
        <version>1.0.11</version>
    </dependency>

    <!-- Spring Boot Starter(可选) -->
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-spring-boot-starter</artifactId>
        <version>1.0.11</version>
    </dependency>

    <!-- OTel OTLP Exporter(agentscope 依赖中已包含 OTel API,这里补充 Exporter) -->
    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-exporter-otlp</artifactId>
    </dependency>
    <!-- Reactor 异步链路上下文传播 -->
    <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-reactor-3.1</artifactId>
        <version>${otel.instrumentation.version}</version>
    </dependency>
</dependencies>

三智能体 Bean 配置

@Configuration
public class AgentScopeConfig {

    @Bean
    public ReActAgent plannerAgent(ChatModel model) {
        return ReActAgent.builder()
            .name("Planner")
            .sysPrompt("""
                你是一个任务规划专家。将用户需求扩展为详细的功能列表。
                每个功能必须包含:名称、描述、验收标准。
                在范围上要大胆,确保功能完整覆盖需求。
                """)
            .model(model)
            .toolkit(minimalReadToolkit())   // Planner 只需读取文档
            .build();
    }

    @Bean
    public ReActAgent generatorAgent(ChatModel model, Toolkit harnessToolkit) {
        return ReActAgent.builder()
            .name("Generator")
            .sysPrompt(loadFromFile("docs/conventions/coding-style.md"))
            .model(model)
            .toolkit(harnessToolkit)          // 完整工具集:文件读写、Shell、MCP
            .memory(new InMemoryMemory())
            .build();
    }

    @Bean
    public ReActAgent evaluatorAgent(ChatModel model) {
        return ReActAgent.builder()
            .name("Evaluator")
            .sysPrompt("""
                你是代码质量评估专家。按以下维度评分(0-10):
                - 功能完整性:是否满足验收标准
                - 代码质量:可读性、命名、结构
                - 测试覆盖:是否有对应测试
                - 架构合规:是否符合分层规则
                返回 JSON 格式评分,并给出具体改进建议。
                """)
            .model(model)
            .toolkit(readOnlyToolkit())       // Evaluator 只需读代码
            .build();
    }

    @Bean
    public Toolkit harnessToolkit(SandboxService sandboxService) {
        Toolkit toolkit = new Toolkit();
        toolkit.registerTool(new FileReadTool());
        toolkit.registerTool(new FileWriteTool(sandboxService));
        toolkit.registerTool(new ShellExecuteTool(sandboxService));
        // MCP 工具注册(按需启用)
        // toolkit.registerMcp("github", "https://mcp.github.com/sse");
        return toolkit;
    }
}

Hook 系统 — 安全边界与约束反馈

agentscope-java 的 Hook 系统是实现 L5/L6 层的关键,在任意推理步骤注入控制逻辑:

// L6 安全边界钩子
@Component
public class SafetyHook implements AgentHook {

    private static final List<String> FORBIDDEN_PATHS = List.of(
        "/etc", "/sys", "~/.ssh", ".env", ".git/config"
    );

    @Override
    public HookPoint getHookPoint() {
        return HookPoint.BEFORE_TOOL_EXECUTION;
    }

    @Override
    public Mono<HookResult> execute(HookContext context) {
        if (containsForbiddenPath(context.getAction())) {
            auditLogger.warn("安全拦截 - {}", context.getAction());
            return Mono.just(HookResult.block("禁止访问受保护系统路径"));
        }
        return Mono.just(HookResult.proceed());
    }
}

// L5 架构约束钩子(文件写入后立即校验)
@Component
public class ConstraintHook implements AgentHook {

    @Override
    public HookPoint getHookPoint() {
        return HookPoint.AFTER_FILE_WRITE;
    }

    @Override
    public Mono<HookResult> execute(HookContext context) {
        return constraintGuard.validate(context.getWrittenFile())
            .map(result -> result.hasViolations()
                // 教学式反馈:包含修复指令,Agent 被纠错的同时被教会
                ? HookResult.feedback(result.toTeachingMessage())
                : HookResult.proceed());
    }
}

Session 管理 — 断点续传

@Service
public class HarnessSessionManager {

    // agentscope-java Session:任务中断后可完整恢复上下文和工具状态
    public ReActAgent restoreOrCreate(String sessionId, ReActAgent agentTemplate) {
        Path sessionPath = Path.of(sessionStorePath, sessionId);
        Session session = new JsonSession(sessionPath);

        boolean loaded = agentTemplate.loadIfExists(session, sessionId);
        log.info(loaded ? "恢复会话:{}" : "新建会话:{}", sessionId);
        return agentTemplate;
    }

    // Sprint 结束后立即保存检查点
    public void checkpoint(ReActAgent agent, String sessionId) {
        Session session = new JsonSession(Path.of(sessionStorePath, sessionId));
        agent.saveTo(session, sessionId);
    }
}

Langfuse 监控对接

对接原理

agentscope-java 已内置 OpenTelemetry,只需将 OTLP Exporter 的端点指向 Langfuse,即可实现零侵入的全链路追踪

agentscope-java 内部执行
  → OTel SDK(agentscope 内置)
  → BatchSpanProcessor
  → OtlpHttpSpanExporter
  → Langfuse /api/public/otel/v1/traces  (OTLP/HTTP,支持 JSON 和 Protobuf)
  → Langfuse UI(Traces / Generations / Evaluations)

注意:Langfuse 目前支持 OTLP over HTTP,不支持 gRPC,需确认 Exporter 使用 HTTP 协议。

OTel → Langfuse 配置

@Configuration
public class LangfuseOtelConfig {

    @Value("${langfuse.base-url}")
    private String langfuseBaseUrl;

    @Value("${langfuse.public-key}")
    private String publicKey;

    @Value("${langfuse.secret-key}")
    private String secretKey;

    @Bean
    @Primary
    public OpenTelemetry openTelemetry() {
        // Langfuse Basic Auth:Base64(publicKey:secretKey)
        String credentials = Base64.getEncoder().encodeToString(
            (publicKey + ":" + secretKey).getBytes(StandardCharsets.UTF_8)
        );

        OtlpHttpSpanExporter exporter = OtlpHttpSpanExporter.builder()
            .setEndpoint(langfuseBaseUrl + "/api/public/otel/v1/traces")
            .addHeader("Authorization", "Basic " + credentials)
            .addHeader("x-langfuse-ingestion-version", "4")
            .build();

        SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
            .addSpanProcessor(BatchSpanProcessor.builder(exporter)
                .setScheduleDelay(Duration.ofSeconds(5))
                .build())
            .setResource(Resource.getDefault().merge(
                Resource.create(Attributes.of(
                    ResourceAttributes.SERVICE_NAME, "java-harness-framework",
                    ResourceAttributes.SERVICE_VERSION, "1.0.0"
                ))
            ))
            .build();

        return OpenTelemetrySdk.builder()
            .setTracerProvider(tracerProvider)
            // W3C Trace Context 传播,确保 Reactor 异步链路不断链
            .setPropagators(ContextPropagators.create(
                W3CTraceContextPropagator.getInstance()
            ))
            .buildAndRegisterGlobal();
    }
}

Harness 语义 Span 属性

为让 Langfuse 正确解析 LLM 调用(显示 token 用量、成本、评分等),按 gen_ai.* 规范注入属性:

@Component
public class HarnessSpanDecorator {

    // gen_ai.* 标准语义(Langfuse 用于识别 LLM Generations)
    public static final AttributeKey<String> GEN_AI_SYSTEM =
        stringKey("gen_ai.system");
    public static final AttributeKey<String> GEN_AI_MODEL =
        stringKey("gen_ai.request.model");
    public static final AttributeKey<Long> GEN_AI_PROMPT_TOKENS =
        longKey("gen_ai.usage.prompt_tokens");
    public static final AttributeKey<Long> GEN_AI_COMPLETION_TOKENS =
        longKey("gen_ai.usage.completion_tokens");

    // Langfuse 业务追踪属性
    public static final AttributeKey<String> LANGFUSE_SESSION_ID =
        stringKey("langfuse.trace.session_id");
    public static final AttributeKey<String> LANGFUSE_USER_ID =
        stringKey("langfuse.trace.user_id");
    public static final AttributeKey<String> LANGFUSE_GEN_NAME =
        stringKey("langfuse.generation.name");

    // Harness 自定义属性
    public static final AttributeKey<String> HARNESS_SPRINT_ID =
        stringKey("harness.sprint.id");
    public static final AttributeKey<String> HARNESS_FEATURE_STATUS =
        stringKey("harness.feature.status");

    public Span startSprintSpan(Feature feature, String sessionId) {
        Tracer tracer = GlobalOpenTelemetry.getTracer("java-harness-framework");
        return tracer.spanBuilder("harness.sprint." + feature.getName())
            .setAttribute(LANGFUSE_SESSION_ID, sessionId)
            .setAttribute(LANGFUSE_GEN_NAME, feature.getName())
            .setAttribute(HARNESS_SPRINT_ID, feature.getId())
            .setAttribute(HARNESS_FEATURE_STATUS, "RUNNING")
            .startSpan();
    }
}

在 Langfuse 中可观测的数据

数据维度 来源 说明
Traces agentscope OTel Spans 完整的 Agent 执行链路(Sprint → Tool Call → LLM Call)
Generations gen_ai.* 属性自动解析 每次 LLM 调用的 input/output/token 用量/成本估算
Sessions langfuse.trace.session_id 按会话聚合的多轮 Agent 交互
Scores Evaluator Agent 评分回写 功能完整性/代码质量/架构合规评分
Latency Span duration 每个工具调用、LLM 调用的耗时分布

评分回写 Langfuse

@Component
public class LangfuseEvalClient {

    // Evaluator Agent 完成评分后,通过 Langfuse API 将评分关联到对应 Trace
    public void submitScore(String traceId, String featureName,
                            double score, String comment) {
        // 使用 Langfuse Java SDK(通过 OTLP 写入或 REST API)
        // 推荐:读取当前 Span 的 traceId,与 Langfuse Trace 对应
        client.scores().create(CreateScoreRequest.builder()
            .traceId(traceId)
            .name("harness_feature_quality")
            .value(score)
            .comment(comment)
            .build());
    }
}

快速开始

环境要求

  • Java 17+(agentscope-java 要求;推荐 Java 21)
  • Maven 3.9+ 或 Gradle 8+
  • Langfuse Cloud 或自托管(版本 ≥ v3.22.0)
  • LLM API Key(支持 Anthropic / OpenAI / DashScope 等)

三步启动

Step 1:配置 pom.xml

<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope</artifactId>
    <version>1.0.11</version>
</dependency>
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>

Step 2:配置环境变量

export ANTHROPIC_API_KEY=sk-ant-...

# 从 Langfuse 项目设置页面获取
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_BASE_URL=https://cloud.langfuse.com  # 或自托管地址

Step 3:运行

@SpringBootApplication
public class HarnessApp {

    @Bean
    CommandLineRunner run(HarnessOrchestrator orchestrator) {
        return args -> {
            orchestrator.execute("实现用户注册登录模块,包含 JWT 认证和邮箱验证")
                .subscribe(report -> {
                    System.out.println("通过率:" + report.getPassRate() + "%");
                    System.out.println("Langfuse 追踪:" + report.getTraceUrl());
                });
        };
    }
}

配置说明

AGENTS.md 规范(地图模式,控制在 100 行以内)

# AGENTS.md — Agent 快速导航地图

## 项目简介
面向企业的任务管理平台,基于 Spring Boot 3 + PostgreSQL。

## 快速导航
| 你想做什么 | 去哪里看 |
|-----------|---------|
| 了解系统架构 | docs/architecture/overview.md |
| 了解模块边界规则 | docs/architecture/boundaries.md |
| 了解编码规范 | docs/conventions/coding-style.md |
| 了解测试规范 | docs/conventions/testing.md |
| 了解当前任务 | docs/plans/current-sprint.md |

## 硬性规则(CI 自动验证,违反即报错含修复指令)
1. 依赖方向:Types → Config → Repository → Service → Runtime → Controller
2. 横切关注点(日志/认证/追踪)只能通过 Provider/Hook 注入
3. 单文件不超过 300 行
4. 新增代码必须有对应测试,覆盖率 ≥ 80%
5. 禁止 System.out.println,统一使用 SLF4J
6. 禁止在 Service 层直接使用 JDBC,统一走 Repository

## 构建与测试
- 全量测试(含架构约束): mvn test
- 构建: mvn package -DskipTests

application.yml

harness:
  llm:
    provider: anthropic
    model: claude-sonnet-4-6
    api-key: ${ANTHROPIC_API_KEY}

  context:
    token-budget: 8000
    agents-md-path: AGENTS.md
    docs-path: docs/

  orchestrator:
    max-sprint-retries: 3
    loop-detection-window: 5
    parallel-features: false   # 建议先用串行,稳定后再开并行

  tools:
    shell:
      sandbox-enabled: true
      allowed-commands: ["git", "mvn", "ls", "cat", "find", "grep"]
    mcp:
      servers: []              # 按需添加 MCP Server

  safety:
    forbidden-paths: ["/etc", "/sys", "~/.ssh", ".env"]
    max-consecutive-failures: 3

  entropy:
    scan-enabled: true
    cron: "0 0 2 * * MON"
    auto-pr: true

langfuse:
  base-url: ${LANGFUSE_BASE_URL:https://cloud.langfuse.com}
  public-key: ${LANGFUSE_PUBLIC_KEY}
  secret-key: ${LANGFUSE_SECRET_KEY}
  enabled: true

扩展指南

自定义工具(agentscope-java AgentTool)

@Component
public class CodeReviewTool implements AgentTool {

    @Override
    public String getName() { return "code_review"; }

    @Override
    public String getDescription() {
        return "对指定文件或目录进行代码审查,返回问题列表和改进建议";
    }

    @Override
    public ToolSchema getSchema() {
        return ToolSchema.builder()
            .param("path", "string", "要审查的文件路径", true)
            .param("focus", "enum", "审查重点", false, "security", "performance", "style")
            .build();
    }

    @Override
    public Mono<String> execute(Map<String, Object> params) {
        return Mono.fromCallable(() -> performReview((String) params.get("path")));
    }
}

自定义 Pipeline(多 Agent 协作)

// 代码生成 → 测试生成 → 代码审查 三阶段 Pipeline
SequentialPipeline codingPipeline = SequentialPipeline.builder()
    .addAgent(generatorAgent)
    .addAgent(testWriterAgent)
    .addAgent(reviewerAgent)
    .build();

// 带结构化输出(最后一个 Agent 返回 POJO)
Msg result = codingPipeline.execute(featureMsg, CodeDeliverable.class).block();
CodeDeliverable deliverable = result.getStructuredData(CodeDeliverable.class);

最佳实践

1. 渐进式落地,从最小 Harness 开始

Phase 1(1-2 天):信息层
  └── 创建 AGENTS.md(地图模式,≤100 行)
  └── 建立 docs/ 结构化目录
  └── 对接 Langfuse(仅配置环境变量,零代码侵入)

Phase 2(3-5 天):约束层
  └── 配置 ArchUnit 分层依赖规则
  └── 错误消息包含 ❌问题 + ✅修复 + 📖文档
  └── CI 流水线集成约束检查

Phase 3(1-2 周):自动化闭环
  └── 接入 agentscope-java(ReActAgent + Hook)
  └── 实现 VerifyPipeline(编译 + ArchUnit + 测试)
  └── 启用 EntropyAgent 定时扫描

2. 让错误消息教会 Agent

// ❌ 无效报错(Agent 不知道怎么改)
throw new ConstraintViolationException("架构违规");

// ✅ 教学式报错(被纠错的同时被教会正确做法)
return HookResult.feedback("""
    [ARCH-001] 架构依赖违规
    ❌ 问题:UserService 直接调用了 UserController(反向依赖)
    ✅ 修复:将共享逻辑提取到 UserDto(Types 层)
    📖 规则:docs/architecture/boundaries.md#layer-rules
    💡 参考:OrderService 是正确的实现示例
    """);

3. 不要用 AI 生成的测试验证 AI 生成的代码

验证链路中必须包含不依赖 Agent 的客观标准

  • ArchUnit 架构约束(机械规则)
  • 已有的人工编写回归测试
  • 编译检查(Java 强类型天然优势)
  • Langfuse 中的人工标注(修正 Evaluator Agent 的评分偏差)

4. 维护活文档

AGENTS.md 不是一次性文档。每当 Agent 犯一个错误,就工程化一个解决方案让它不再重犯,然后更新 AGENTS.md。这是 Harness Engineering 的核心循环。

5. agentscope-java 响应式使用规范

// ❌ 严禁在非 main/test 代码中使用 .block()
agent.call(msg).block();  // 阻塞,破坏响应式链!

// ✅ 保持响应式链
agent.call(msg)
    .flatMap(result -> verifyPipeline.verify(result))
    .subscribe(verified -> handleResult(verified));

// ❌ 严禁 Thread.sleep(),使用 Mono.delay() 替代

6. Langfuse 使用规范

  • langfuse.trace.session_id 将同一任务的所有 Agent 调用关联到同一 Session
  • langfuse.generation.name 标注 Feature 名称,便于按业务维度过滤
  • 自托管 Langfuse 需确保版本 ≥ v3.22.0(OTLP 端点最低版本要求)
  • 定期在 Langfuse UI 审查低分 Generation,根据规律更新 AGENTS.md 规则

路线图

v1.0(当前目标)

  • agentscope-java 核心集成(ReActAgent + Hook + Session + PlanNotebook)
  • Langfuse OTLP 对接(零侵入)
  • HarnessOrchestrator(Planner-Generator-Evaluator 三角架构)
  • VerifyPipeline(编译 + ArchUnit + 单元测试 + LLM 评分)
  • LoopDetector + 人工升级通知
  • Spring Boot Starter

v1.1

  • MCP Server 管理(多 MCP 路由、权限控制)
  • Langfuse Evaluation 自动回写(Evaluator 评分 → Langfuse Score API)
  • Langfuse Prompt Management 集成(版本化 Prompt,生产环境动态更新)
  • EntropyAgent(定时扫描 + 重构 PR 生成)

v1.2

  • 并行 Agent 调度(agentscope Pipeline 并行模式)
  • Long-term Memory 向量检索(agentscope 扩展 + Qdrant)
  • GraalVM 原生镜像支持(适配 Serverless 场景)
  • A2A(Agent-to-Agent)协议支持

v2.0(长期)

  • 预制 Harness 模板(Java/Spring 黄金路径)
  • 基于 Langfuse 历史 Trace 数据的智能熵预测
  • 多模型动态路由(按任务类型自动选择最优模型)

参考资料


本文档由 Java Harness Framework 项目组维护。每当 Agent 犯错,工程化解决方案并更新本文档。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages