HarnessAgent 扩展 ReActAgent 机制深度解析

项目地址:https://github.com/agentscope-ai/agentscope-java

本文结合源码分析 HarnessAgent 如何在不修改 ReActAgent 代码的前提下,通过三种正交机制将 Core 引擎扩展为生产一站式解决方案。每个机制附带执行路径图和伪代码。


1. 架构总览:三种扩展机制

HarnessAgent 不继承 ReActAgent,而是通过组合 + 委托持有它。所有扩展通过三个正交机制实现,ReActAgent 的代码一行不改:

复制代码
机制一:wrappedCall() --- 外层包装
├─ 沙箱生命周期(Mono.using acquire/release)
├─ 上下文溢出紧急恢复(onErrorResume + retry)
└─ RuntimeContext 富化(注入 SandboxContext/FS/WSManger)

机制二:中间件注入 -- Core 循环内的横切增强
├─ onSystemPrompt: WorkspaceContext, Skills
├─ onReasoning: Compaction, AtPathExpansion, Trace
├─ onActing: ToolResultEviction, PlanMode, Trace
└─ onAgent: MemoryFlush, MemoryMaintenance

机制三:工具注册 -- 让 Agent 能操作 Harness 基础设施
├─ FilesystemTool → AbstractFilesystem(多态后端)
├─ ShellExecuteTool → AbstractSandboxFilesystem(仅沙箱)
├─ MemorySearchTool/GetTool → WorkspaceManager
└─ PlanModeTools / SubagentTools
ReActAgent (Core) − 不被修改
├─ ReAct 循环 / 模型调用 / 工具执行 / 权限 / HITL / 状态
└─ 预留扩展点:5条中间件钩子 + Toolkit注册接口 + delegate模式

2. 机制一:外层 call () 包装

复制代码
HarnessAgent.java line 731--757 (wrappedCall())

为什么需要外层包装?

有些行为不适合放在 ReActAgent 的中间件链里:

  • 沙箱生命周期:必须在整个 call(包括所有中间件)的前后管理资源,放在 onAgent 链里的话,链之前的逻辑就无法使用沙箱
  • 溢出恢复:需要 onErrorResume + 重试整个 call,超出了中间件 "围绕某个阶段做增强" 的能力
  • RuntimeContext 富化:需要在调用 delegate 前往上下文中塞入 Harness 专属对象

执行路径

复制代码
HarnessAgent.call(msg, runtimeContext)
├─ ensureSessionDefaults(runtimeContext)
│    ├─ 补充默认 sessionId (fallback agent name)
│    ├─ put(SandboxContext.class, defaultSandboxContext)
│    ├─ put(AbstractFilesystem.class, wsManager.getFilesystem())
│    ├─ put(WorkspaceManager.class, wsManager)
│    └─ put(WorkspacePathNormalizer.class, pathNormalizer)
│       ← enriched RuntimeContext
└─ wrappedCall(msg, enrichedCtx, () → delegate.call(msg, enrichedCtx))
    ├─【层1】Mono.using − 沙箱生命周期
    │    resourceInit:
    │        sandboxLifecycleMw.acquireForCall(ctx)
    │        ├─ SandboxManager.acquire()
    │        ├─ sandbox.start()
    │        └─ filesystemProxy.setSandbox(sandbox) 注入虚拟沙箱
    │    inner.get():
    │        delegate.call(msg, enrichedCtx)
    │        └─ reasoning → acting → iterate...
    │           (中间件链在此内部运行)
    │    resourceCleanup:
    │        sandboxLifecycleMw.releaseForCall(ctx)
    │        ├─ persistState()          保存沙箱状态JSON
    │        ├─ sandbox.stop()           持久化快照(tar归档)
    │        ├─ sandbox.shutdown()
    │        └─ filesystemProxy.setSandbox(null) 清除引用
    ├─【层2】onErrorResume − 上下文溢出紧急恢复
    │    if compactionHook != null:
    │        return base.onErrorResume(error => {
    │            if isContextOverflowError(error): // 字符串匹配检测 "context_length_exceeded"
    │                recoverFromOverflow(msg, ctx)
    │                └─ forceCompactAndRetry()   // 强制压缩对话{triggerMessages=1}
    │                   重新调用 delegate.call()  用压缩后的上下文重试
    │            return Mono.error(error)         // 非溢出错误原样抛出
    │        })
    └─ return base

伪代码

复制代码
wrappedCall(Msgs, ctx, innerSupplier):
    // ===== 层1:沙箱生命周期 =====
    // Mono.using(resourceInit, body, resourceCleanup)
    // 保证 acquire 和 release 严格配对,即使 body 抛异常也会执行 cleanup
    base = Mono.using({
        init = () => {
            if sandboxLifecycleMw != null:
                sandboxLifecycleMw.acquireForCall(ctx)
                // 内部: SandboxManager.acquire() → sandbox.start() → proxy.setSandbox()
        },
        body = () => innerSupplier.get(), // delegate.call(msgs, ctx)
        cleanup = () => {
            if sandboxLifecycleMw != null:
                sandboxLifecycleMw.releaseForCall(ctx)
            // 内部: persistState() → sandbox.stop() → sandbox.shutdown() → proxy.clear()
        }
    })

    // ===== 层2:溢出恢复 =====
    if compactionHook != null:
        return base.onErrorResume(error => {
            if isContextOverflowError(error): // 字符串匹配 "context_length_exceeded"
                recoverFromOverflow(msgs, ctx)
                // 强制压缩 − 重试整个 call
                return base
        })
    return Mono.error(error) // 非溢出错误原样传播

    return base

关键方法说明

方法 功能
ensureSessionDefaults(ctx) 往 RuntimeContext 中注入 SandboxContext、AbstractFilesystem、WorkspaceManager 等 Harness 对象
wrappedCall(msgs, ctx, inner) 外层包装入口,叠加沙箱生命周期和溢出恢复两层
acquireForCall(ctx) 获取 / 创建沙箱并注入到文件系统代理(被 Mono.using 的 init 调用)
releaseForCall(ctx) 持久化状态、停止 / 销毁沙箱、清除代理引用(被 Mono.using 的 cleanup 调用)
isContextOverflowError(e) 通过字符串匹配检测各种 LLM 提供商的上下文溢出错误信息
recoverFromOverflow(msgs, ctx) 强制压缩对话历史后重试整个 call
forceCompactAndRetry() 以 triggerMessages=1 触发 ConversationCompactor,然后重新调用 delegate

为什么不把沙箱做成 onAgent 中间件?

SandboxLifecycleMiddleware 虽然实现了 ,但没有重写任何钩子方法。它的 是被 直接调用的公开方法。 原因:

复制代码
如果沙箱放在 onAgent 中间件链里:
onAgent_MW1 → onAgent_MW2 → ... → SandboxMW.onAgent → core
                                ↑
                                此时沙箱才可用
但 MW1/MW2 可能需要访问文件系统(如 WorkspaceContextMiddleware 读 AGENTS.md)
此时沙箱还没启动,文件系统代理是空 → 报错

放在 wrappedCall() 的 Mono.using init 层:
acquireSandbox() → onAgent_MW1 → onAgent_MW2 → ... → core
↑
所有中间件执行时沙箱都已就绪 ✓

3. 机制二:中间件注入

复制代码
HarnessAgent.java line 1904--2207 (build 中的注入)

ReActAgent 预留的 5 条子链

ReActAgent 在循环的各阶段通过 MiddlewareChain.build()

"洋葱模型"(Onion Model)是中间件架构中的一个经典比喻,指的是多层嵌套。由外向内再由内向外的执行顺序,就像洋葱一层套一层。每一层中间件包裹着内层请求,请求从最外层穿透到核心,响应再从核心向外返回。

钩子 触发时机 模式 ReActAgent 源码位置
onAgent 包裹整个 agent 调用 洋葱 (before/after) line 848
onSystemPrompt 系统提示词构建时 管线(顺序变换) line 859
onReasoning 每次 LLM 推理调用前后 洋葱 line 1888
onModelCall 每次原始 model.stream () 前后 洋葱 line 2029
onActing 每次工具批量执行前后 洋葱 line 2186

每个中间件只重写需要的钩子,未重写的默认传递 return next.apply(input)

执行路径:13 个中间件在循环中的位置

复制代码
delegate.call(msg, ctx)
┌─────────────────────────────────────────────────────┐
│ onAgent 链 (包裹整个调用)                             │
│ MemoryFlushMiddleware.onAgent                        │
│  → next.apply(input).doOnComplete(() => doFlush())  │
│    调用完成后用 LLM提取记忆写入MEMORY.md              │
│ MemoryMaintenanceMiddleware.onAgent                  │
│  → next.apply(input).doOnComplete(() => maintain())  │
│    调用完成后检查是否需要归档/整合/清理                │
└─────────────────────────────────────────────────────┘
ReAct Loop
┌─────────────────────────────────────────────────────┐
│ onSystemPrompt 链(管线式追加)                       │
│ WorkspaceContextMiddleware                           │
│  → 追加 AGENTS.md /MEMORY.md/环境/日期               │
│ HarnessSkillMiddleware                               │
│  → 追加 <available_skills> 技能列表                  │
└─────────────────────────────────────────────────────┘
reasoning(iter)
┌─────────────────────────────────────────────────────┐
│ onReasoning 链                                       │
│ CompactionMiddleware                                 │
│  → 检查长度,超阈值则压缩后再传给next                │
│ AtPathExpansionMiddleware                            │
│  → 展开用户消息中的 @path 引用                       │
│ AgentTraceMiddleware                                 │
│  → 记录推理日志                                      │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ onModelCall 链                                       │
│ AgentTraceMiddleware                                 │
│  → 记录模型调用日志                                  │
│    └ model.stream() ←唯一LLM调用点                    │
└─────────────────────────────────────────────────────┘
acting(iter)
┌─────────────────────────────────────────────────────┐
│ onActing 链                                          │
│ ToolResultEvictionMiddleware                         │
│  → 超大结果卸载到文件,替换为预览占位符 ||            │
│ PlanModeMiddleware                                   │
│  → Plan Mode下拦截修改工具                            │
│ AgentTraceMiddleware                                 │
│  → 记录工具执行日志                                  │
│ SubagentsMiddleware                                  │
│  → 推送已完成的后台任务结果                          │
│    └ toolkit.callTools() 实际执行工具                 │
└─────────────────────────────────────────────────────┘
executeIteration(iter+1)

四种中间件模式详解

Before 模式:CompactionMiddleware (onReasoning)

在 LLM 调用前变换输入,不影响后续流程。

复制代码
CompactionMiddleware.onReasoning(agent, ctx, input, next):
    messages = input.messages
    systemMsg = messages[0]        // 第一条是系统提示词
    conversation = messages[1..]   // 剩余是对话历史

    compacted = ConversationCompactor.compactIfNeeded(conversation)
    // 检查 token 是否超过阈值
    // 超过 − 用 LLM 将消息摘要为摘要
    // 未超过 − 返回原始消息

    if compacted != original:
        applyToContext(compacted)              // 替换 AgentState.context
        newInput = ReasoningInput(compacted, systemMsg, options)
        return next.apply(newInput)            // 用压缩后的输入传递
    else:
        return next.apply(input)               // 原样传递
After 模式:MemoryFlushMiddleware (onAgent)

在整个 call 完成后触发后置操作。

复制代码
MemoryFlushMiddleware.onAgent(agent, ctx, input, next):
    return next.apply(input)          // 先让整个 agent 调用完成
        .doOnComplete(() => {
            doFlush(agent, ctx).subscribe()
            // 用 LLM 从对话中提取值得记住的内容
            // 写入 memory/YYYY-MM-DD.md
            // 将 session 日志归档到 JSONL 文件
        })
Pipeline 模式:WorkspaceContextMiddleware (onSystemPrompt)

顺序追加内容到系统提示词,多个中间件依次变换。

复制代码
WorkspaceContextMiddleware.onSystemPrompt(agent, ctx, prompt):
    builder = new StringBuilder(prompt)
    builder.append(readAGENTS.md)        // 项目指令
    builder.append(readMEMORY.md)       // 长期记忆
    builder.append(readKNOWLEDGE.md)     // 知识库
    builder.append(currentDate())       // 当前日期
    builder.append(osInfo)              // 操作系统信息
    builder.append(workspacePaths)     // 工作区路径
    return Mono.just(builder.toString()) // 传给下一个 onSystemPrompt 中间件
Gate 模式:PlanModeMiddleware (onActing)

拦截并拒绝不符合条件的工具调用。

复制代码
PlanModeMiddleware.onActing(agent, ctx, input, next):
    if planModeActive:
        filtered = input.toolCalls.filter(tool =>
            tool.isReadOnly() OR tool.name in planExtraAllowed
        )
        for each rejected in (input.toolCalls − filtered):
            emit ToolResultBlock("Denied: plan mode restricted")
        return next.apply(ActingInput(filtered)) // 只放行只读工具
    else:
        return next.apply(input)                 // 非Plan Mode, 全部放行

4. 机制三:工具注册

复制代码
HarnessAgent.java line 1777, 2007--2048, 2227--2228

执行路径

复制代码
Builder.build()
├─ agentToolkit = this.toolkit.copy()        ← 深拷贝,隔离不同Agent实例
├─ 注册 Harness 专属工具 (在 agentToolkit 上):
│    ├─ MemorySearchTool(wsManager)
│    │    搜索记忆文件内容,底层走 AbstractFilesystem
│    ├─ MemoryGetTool(wsManager)
│    │    读取指定记忆文件
│    ├─ SessionSearchTool(wsManager)
│    │    搜索历史会话日志
│    ├─ FilesystemTool(filesystem, normalizer)
│    │    统一文件操作入口,多态适配 Local/Sandbox/Remote
│    │    read/write/edit/grep/ls/upload/download/move
│    ├─ ShellExecuteTool(sandbox)
│    │    ← 仅当 filesystem instanceof AbstractSandboxFilesystem
│    │    Shell命令执行,委托给沙箱后端
│    │    安全边界由注册条件保证
│    ├─ PlanEnterTool / PlanWriteTool / PlanExitTool ← Plan Mode 控制
│    ├─ AgentSpawnTool / TaskTool                   ← 子Agent编排(来自SubagentsMiddleware)
│    ├─ SkillManageTool / ProposeSkillTool          ← 技能自学习
│    └─ NCP Server Tools                            ← 通过 NcpServerRegistrar 动态注册
├─ inner.toolkit(agentToolkit)        ← 最后传给 Core
└─ delegate = inner.build()           ← ReActAgent 构造,收集 toolkit

伪代码

复制代码
// build() 中的工具注册流程
agentToolkit = toolkit.copy()            // 深拷贝,避免污染共享模板

// 记忆工具 → 注入 WorkspaceManager
agentToolkit.registerTool(new MemorySearchTool(wsManager))
agentToolkit.registerTool(new MemoryGetTool(wsManager))
agentToolkit.registerTool(new SessionSearchTool(wsManager))

// 文件系统工具 → 注入多态 AbstractFilesystem
agentToolkit.registerTool(new FilesystemTool(filesystem, pathNormalizer))
// FilesystemTool 内部: abstractFilesystem.read(runtimeContext, norm(path), ...)
// 同一个 Tool 代码, filesystem 可能是 Local/Sandbox/Remote → 零改动切换后端

// Shell工具 − 仅沙箱模式注册 (注册条件 = 安全边界)
if filesystem instanceof AbstractSandboxFilesystem sandbox:
    agentToolkit.registerTool(new ShellExecuteTool(sandbox))
    // ShellExecuteTool 内部: sandbox.execute(runtimeContext, command, timeout)

// Plan Mode 工具
if planModeEnabled:
    agentToolkit.registerTool(new PlanEnterTool(planModeManager))
    agentToolkit.registerTool(new PlanWriteTool(planModeManager))
    agentToolkit.registerTool(new PlanExitTool(planModeManager))

// 子Agent工具(从中间件获取)
if dynamicSubagents:
    for tool in dynMw.getTools():
        agentToolkit.registerTool(tool)

// 最后传给 Core
inner.toolkit(agentToolkit)
delegate = inner.build()
// ReActAgent 构造时: toolkit.getToolSchemas() 收集所有工具的 schema
// ReActAgent 循环中: toolkit.callTools() 分发执行 → 和普通工具一样被调度

工具与 Harness 基础设施的连接方式

每个 Harness 工具通过构造函数注入 获得基础设施引用,ReActAgent 对它们完全无感知:

复制代码
┌─────────────────────┐          ┌─────────────────────────────┐
│ FilesystemTool      │◄─────────┤ AbstractFilesystem         │
│ · read/write/edit/ls│构造注入   │ (多态: Local/Sandbox/Remote) │
└─────────────────────┘          └─────────────────────────────┘
        ↑
        │ 运行时通过 RuntimeContext 传递 userId/sessionId
        │ AbstractFilesystem 据此做命名空间隔离

┌─────────────────────┐          ┌─────────────────────────────┐
│ ShellExecuteTool    │◄─────────┤ AbstractSandbox            │
│ · execute(command)  │构造注入   │ Filesystem                  │
└─────────────────────┘          │ (Local/Docker/K8s)          │
                                 └─────────────────────────────┘
                                 ↑ execute() 在容器/Pod内执行
                                 本地模式下宿主直接执行

┌─────────────────────┐          ┌─────────────────────────────┐
│ MemorySearchTool    │◄─────────┤ WorkspaceManager            │
│ · search(query)     │构造注入   │ · listMemoryFiles()         │
└─────────────────────┘          │ · readUtf8()                │
                                 └─────────────────────────────┘
                                          ↳ 间接使用Filesystem

涉及的方法

方法 功能
toolkit.copy() 深拷贝 Toolkit,确保不同 Agent 实例的工具集互相隔离
agentToolkit.registerTool(tool) 向 Toolkit 注册一个工具,自动生成 ToolSchema
inner.toolkit(agentToolkit) 将填充好的 Toolkit 设置到 ReActAgent.Builder 上
FilesystemTool(filesystem, normalizer) 构造时注入多态文件系统和路径规范化器
ShellExecuteTool(sandbox) 构造时注入沙箱文件系统(仅沙箱模式下创建)
MemorySearchTool(wsManager) 构造时注入 WorkspaceManager,间接使用文件系统
NcpServerRegistrar.register(toolkit, servers) 动态注册 MCP 服务器暴露的工具

5. build() 装配全流程

复制代码
HarnessAgent.java line 1774--2249

Builder.build() 是三种机制的交汇点,按严格顺序装配:

复制代码
Builder.build()
├─【Step 1】Toolkit 深拷贝                        line 1777
│   agentToolkit = this.toolkit.copy()
├─【Step 2】文件系统解析                         line 1780--1849
│   filesystem = resolveFilesystem(spec, workspace, nsFactory)
│    互斥校验: sandbox vs remote vs local vs raw
│    生成 NamespaceFactory (userid → 命名空间前缀)
├─【Step 3】分布式存储校验                       line 1806--1844
│   if distributedStore:
│       自动注入 stateStore / snapshotSpec / executionGuard
│       if remoteFilesystem + localStateStore:
│           throw IllegalStateException       ← 一致性强制
├─【Step 4】WorkspaceManager 创建                line 1885--1887
│   wsManager = new WorkspaceManager(workspace, filesystem, index, nsFactory)
├─【Step 5】沙箱组装(如配置了沙箱)              line 1855--1884
│   capturedSandboxFs = new SandboxBackedFilesystem()  ← 代理
│   filesystem = capturedSandboxFs
│   sandboxManager = new SandboxManager(client, stateStore, agentId, guard)
│   sandboxLifecycleMw = new SandboxLifecycleMiddleware(manager, proxy)
├─【Step 6】中间件注入 → inner.middleware(...)    line 1904--2207
│   按顺序注入 13 个中间件 (详见第3节执行路径图)
├─【Step 7】工具注册 → agentToolkit.registerTool(...) line 2007--2048
│   注册所有 Harness 专属工具(详见第4节执行路径图)
├─【Step 8】传给 Core 并构建                     line 2227--2228
│   inner.toolkit(agentToolkit)
│   delegate = inner.build()
│   // ReActAgent 构造时:
│   //   middlewares = [GracefulShutdownMW] + builder.middlewares
│   //   toolkit = agentToolkit (含所有 Harness 工具)
└─【Step 9】构造 HarnessAgent                     line 2231--2249
    new HarnessAgent(delegate, wsManager, sandboxLifecycleMw, ...)
    // 保存引用供 wrappedCall() 使用

6. 三种机制的协作关系

以一个完整的 call() 为例,展示三种机制如何在运行时协同:

复制代码
HarnessAgent.call(msg, ctx)
┌─────────────────────────────────────────────────────────────┐
│ 机制一:外层包装                                             │
│ ensureSessionDefaults(ctx)              富化 RuntimeContext    │
│ wrappedCall():                                              │
│   acquireForCall(ctx)                   启动沙箱容器          │
│   └─ delegate.call(msg, enrichedCtx)                       │
│       ┌─────────────────────────────────────────────────┐  │
│       │ 机制二 + 三: Core 循环                           │  │
│       │ onAgent: MemoryFlushMW          注册完成后回调    │  │
│       │ reasoning(0):                                    │  │
│       │   onSystemPrompt:                                │  │
│       │      追加 AGENTS.md /MEMORY.md/技能列表           │  │
│       │   onReasoning: CompactionMW     压缩过长上下文    │  │
│       │   onModelCall: TraceMW          记录日志          │  │
│       │   model.stream()                LLM 回复包含 ToolUseBlock
│       │ acting(0):                                       │  │
│       │   onActing: PlanModeMW           检查是否允许执行 │  │
│       │   evaluatePermissions()          权限门控         │  │
│       │   toolkit.callTools()                            │  │
│       │       ├─ FilesystemTool.read() ←机制三: 通过 AbstractFilesystem 读文件
│       │       └─ ShellExecuteTool.exec() ←机制三: 通过 Sandbox 执行命令
│       │   onActing: EvictionMW           超大结果卸载到文件
│       │ reasoning(1) → acting(1) → ...   继续迭代
│       └─ return finalMsg
│   releaseForCall(ctx)                   停止沙箱、持久化快照
│   onErrorResume(overflow?)              溢出则压缩重试
└─────────────────────────────────────────────────────────────┘
│ MemoryFlushMW.doOnComplete → doFlush()   异步提取记忆

7. 方法速查表

外层包装(机制一)

方法 功能
ensureSessionDefaults(ctx) 富化 RuntimeContext,注入 SandboxContext/FS/WSManager
wrappedCall(msg, ctx, inner) 外层包装入口:沙箱生命周期 + 溢出恢复两层
wrappedStreamEvents(msg, ctx, inner) 流式版本的外层包装(无溢出恢复)
acquireForCall(ctx) 获取 / 创建沙箱,注入文件系统代理
releaseForCall(ctx) 持久化状态,停止 / 销毁沙箱,清除代理
isContextOverflowError(e) 字符串匹配检测上下文溢出错误
recoverFromOverflow(msg, ctx) 强制压缩后重试整个 call

中间件(机制二)

中间件 钩子 模式 功能
SandboxLifecycleMiddleware 无(外部调用) --- 沙箱 acquire/release
WorkspaceContextMiddleware onSystemPrompt Pipeline 追加工作区上下文到系统提示
CompactionMiddleware onReasoning Before 推理前压缩过长上下文
AtPathExpansionMiddleware onReasoning Before 展开 @path 引用
MemoryFlushMiddleware onAgent After call 后提取记忆
MemoryMaintenanceMiddleware onAgent After 定期归档 / 整合 / 清理
ToolResultEvictionMiddleware onActing Around 超大结果卸载文件
PlanModeMiddleware onActing Gate Plan Mode 拦截非只读工具
AgentTraceMiddleware onReasoning/onActing/onModelCall Around 结构化可观测日志
HarnessSkillMiddleware onSystemPrompt/onReasoning Pipeline+Before 技能解析与注入
SkillUsageMiddleware onActing After 技能调用计数
SkillCuratorMiddleware onAgent After 技能自动晋升 / 降级
SubagentsMiddleware onSystemPrompt/onActing Pipeline+After 子 Agent 编排与任务推送

工具注册(机制三)

工具 注入依赖 功能
FilesystemTool AbstractFilesystem + PathNormalizer 统一文件操作(read/write/edit/grep/ls/upload/download)
ShellExecuteTool AbstractSandboxFilesystem Shell 命令执行,(仅沙箱模式注册)
MemorySearchTool WorkspaceManager 关键词搜索记忆文件
MemoryGetTool WorkspaceManager 读取指定记忆文件
SessionSearchTool WorkspaceManager 搜索历史会话日志
PlanEnterTool/WriteTool/ExitTool PlanModeManager Plan Mode 进入 / 写入 / 退出
AgentSpawnTool/TaskTool SubagentsMiddleware 子 Agent 生成与任务管理
SkillManageTool/ProposeSkillTool SkillCurator 技能自创建 / 编辑 / 提议

build() 装配

步骤 方法 功能
Step1 toolkit.copy() 深拷贝 Toolkit
Step2 resolveFilesystem(...) 解析文件系统后端(互斥校验)
Step3 一致性校验 Remote+LocalState → throw; Sandbox+LocalState → warn
Step4 new WorkspaceManager(...) 创建工作区管理器
Step5 new SandboxLifecycleMiddleware(...) 组装沙箱中间件 + 代理
Step6 inner.middleware(...) ×13 注入中间件到 Core
Step7 agentToolkit.registerTool(...) ×N 注册 Harness 工具
Step8 inner.toolkit() + inner.build() 传给 Core 并构造 ReActAgent
Step9 new HarnessAgent(delegate,...) 构造 HarnessAgent

8. 源码索引

文件 关键内容
harness/.../HarnessAgent.java Builder.build() 装配全流程 (line 1774--2249)、wrappedCall() (line 731--757)
harness/.../middleware/SandboxLifecycleMiddleware.java acquireForCall/releaseForCall(不走中间件链)
harness/.../middleware/CompactionMiddleware.java onReasoning: Before 模式压缩上下文
harness/.../middleware/MemoryFlushMiddleware.java onAgent: After 模式提取记忆
harness/.../middleware/WorkspaceContextMiddleware.java onSystemPrompt: Pipeline 模式追加上下文
harness/.../middleware/ToolResultEvictionMiddleware.java onActing: Around 模式卸载超大结果
harness/.../middleware/PlanModeMiddleware.java onActing: Gate 模式拦截非只读工具
harness/.../middleware/HarnessSkillMiddleware.java onSystemPrompt/onReasoning: 技能解析注入
harness/.../middleware/SubagentsMiddleware.java onSystemPrompt/onActing: 子 Agent 编排
harness/.../tool/FilesystemTool.java 统一文件操作,注入 AbstractFilesystem
harness/.../tool/ShellExecuteTool.java Shell 执行,注入 AbstractSandboxFilesystem
harness/.../tool/MemorySearchTool.java 记忆搜索,注入 WorkspaceManager
core/.../middleware/MiddlewareBase.java 中间件基类:5 个钩子方法的默认遗传实现
core/.../middleware/MiddlewareChain.java 洋葱模型链构建器
core/.../ReActAgent.java 5 条链的触发点:line 848/589/1888/2029/21
相关推荐
Luhui Dev10 小时前
用 AI 生成一道几何题配图:三角形四心作图案例
人工智能·数学·agent·luhuidev
爬楼的猪10 小时前
html-edge-tts-video: 用AI创建有声视频
人工智能·ai编程
咖小君10 小时前
github每日一更-【Stop Slop】【教AI删掉自己写作马脚的开源Skill】
人工智能·创业
qdprobot10 小时前
齐护AIOT科创社团学习套件桌面总程AiTall V3版人工智能Mixly图形化编程AI小智物联网AI具身智能应用椴木科创作品
人工智能·物联网·学习
武子康10 小时前
Fable 5 的 7 月 19 日不是发布延期:模型可用性正在变成动态资源(九维可用性 + SLO 重构)
人工智能·chatgpt·claude
亦暖筑序10 小时前
AgentScope-Java 入门:保存评审状态并生成 Markdown 报告
java·人工智能·后端
水如烟10 小时前
孤能子视角:三十六计之连环计——拓扑结构重构
人工智能
茶马古道的搬运工10 小时前
MiniMax Agent Team 深度解析:用对抗式多 Agent 架构解决长程任务
人工智能
程序猿编码10 小时前
没有AI框架,没有GPU,一个C语言文件跑通大模型
c语言·开发语言·人工智能·深度学习·ai·大模型
程序媛kelly10 小时前
.xml / .jrxml 文件怎么打开?OpenFiles 实测预览、编辑、搜索与 AI 摘要排查流程
xml·人工智能·jrxml