AgentScope第16式·归元框架

AgentScope第16式·Harness

把手工装配的 Agent 交给 Harness,交出去的不只是代码,还有装配顺序的决定权。

[读者] 已用 AgentScope Java 跑通 ReAct + Tool + MCP + Memory 的 Java 后端
[痛点] runtime 装配段越堆越长,每加一个能力都要改同一处
[现在读] 系列走到第 16 式,装配权该由框架收回了
[读完] 能用 HarnessAgent 替换手工装配,并说清它自动给了什么
[旧方案] 手工 new ReActAgent + 逐个注册工具与能力
    |
    v
[新需求] 统一装配 Workspace / Memory / Compaction / Skill / Plan / Sandbox / Subagent / MCP
    |
    v
[冲突] 装配逻辑散落在业务 runtime,顺序与开关没人负责
    |
    v
[后果] 每次加能力都在改同一段,回归边界不可控

我是老李,带一个小团队做企业数字人。从第 3 式把最小 Demo 立起来之后,这个项目就成了整个系列的宿主:注册登录、项目 CRUD、运行页 /run/{projectId}、LiveKit 房间、Realtime Bridge,场景一直没换过,教程代码在 https://github.com/lifuchun522/agentscopepractice ,版本基线固定为 AgentScope Java v2.0.3。

过去十几式,我们一直在这个宿主上做加法:工具、MCP、权限、状态、Memory、Skill、Plan、Sandbox、Subagent 陆续接进来,第 15 式还走完了一次上游 Issue/PR 的贡献闭环。加法都落在同一段装配代码里——构造 Agent 的那几十行。

这一周,我们在这个宿主上做一件不太一样的事:不是再加能力,而是换掉装配方式。

装配权到底该留在业务代码手里,还是交给框架?

是继续在 AvatarRuntime 里加 if,还是把 ReActAgent 换成 HarnessAgent?

如果换错了,代价是功能全在、却没人说得清哪些能力到底是谁开的?

01、故事

周五下午的评审,白板上贴着前十五式的能力清单。运行页 /run/{projectId} 打开,LiveKit 房间建立,Realtime Bridge 把会话事件转给 AgentScope,再把文本回推给前端。链路是通的。

问题出在链路中间那一层。AvatarRuntime 这个类,从最初几十行的构造方法,长成了很长的装配段:先建 Toolkit,逐个 register;再建 Memory;再决定压缩挂在哪一步后面;再判断这个项目开不开 Plan、装不装 Skill;最后 new 一个 ReActAgent。每加一项能力,就多一段分支。

任务是:把数字人运行时从手工拼装的 ReActAgent 迁移到 HarnessAgent,保留已经注册好的工具与权限,并让迁移前后核心业务用例全部回归通过。

会上有两种意见。一种主张直接重写装配层,理由是能力都测过了;另一种主张先读源码,搞清楚 HarnessAgent 到底包了什么、自动开了什么,再决定删什么。我们选了后者——前面吃过一次亏:某个能力的挂载顺序被顺手改掉,直到回归时才发现。

真正让我们下决心的不是懒,而是一个判断:装配顺序本身就是设计,它不该只活在某个人的记忆里。

场景未更换
宿主只一个
装配要移交
回归先立好

02、问题

旧方案失效不是因为它跑不通,而是因为它不可控。下面是迁移前装配段的结构示意(字段名与调用形态以 v2.0.3 源码为准):

public final class AvatarRuntimeV1 {

    private final AvatarProjectService projectService;
    private final ModelRouter modelRouter;
    private final McpClientRegistry mcpClients;

    public ReActAgent build(AvatarProject project) {
        Toolkit toolkit = new Toolkit();
        toolkit.register(new ProjectCrudTools(projectService));
        toolkit.register(new McpToolkit(mcpClients));

        Memory memory = new InMemoryMemory();
        PermissionGuard guard = new PermissionGuard(project.getPolicy());

        return ReActAgent.builder()
                .name(project.getAgentName())
                .model(modelRouter.forName(project.getModel()))
                .sysPrompt(project.getSystemPrompt())
                .toolkit(toolkit)
                .memory(memory)
                .middleware(guard)
                .build();
    }
}

三种失效表现:

第一是顺序耦合。Memory 装在哪、压缩挂在谁后面、权限包在哪一层,全靠读代码推断,改动一次就要重新推一遍。

第二是开关散落。压缩、Plan、Skill 的开关分散在 runtime 的不同分支里,同一个能力在装配、运行、日志三处各有一套判断。

第三是回归边界模糊。改一行装配,说不清影响哪些用例,只能全量重跑。

业务影响也很直接:加一个能力的时间,大部分花在确认「有没有把上一个能力碰坏」,而不是花在新能力本身。

本篇的完成标准有三条:一是运行时装配收敛到一个 HarnessAgent 构建入口;二是已注册的工具与权限在 Harness 管线下仍生效;三是迁移前后核心业务用例全部回归,且能列出一张「Harness 自动提供了什么」的清单。

代码会说话
顺序即契约
开关不收拢
回归无边界

03、原理

先划名词边界。ReActAgent 是推理循环本体:想一步、调一次工具、再想;Middleware 是挂在 Agent 生命周期切点上的可插拔单元,在推理或工具调用前后做事;Toolkit 是工具的统一注册与分发容器。三者关系里,HarnessAgent 是外层装配者。

反直觉判断一:HarnessAgent 的价值不是让 Agent 更聪明,而是让装配权归一。

官方架构文档 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/docs/v2/zh/docs/harness/architecture.md 与核心类 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java 描述的是同一件事:推理循环仍然由 ReActAgent 承担,Harness 层负责把 Workspace、Memory、Compaction、Skill、Plan Mode、Filesystem、Sandbox、Subagent、MCP 这些能力,按统一顺序装进管线。

换句话说,你换掉的不是推理引擎,而是「谁来负责装配」——以及这份装配顺序有没有被写进框架,而不是写在你的 runtime 里。

反直觉判断二:能力越多,越不该由业务代码装配。

能力少的时候,手工装配成本低、可见性高;能力一多,装配顺序、开关组合、状态归属会呈组合式增长,业务代码里就出现大量只为「把它们按某种顺序放好」而存在的行。这些行不产生业务价值,却必须被 review。

这也解释了两件事。第一,为什么 Harness 的入口是 Middleware + Toolkit 而不是更多 API:中间件负责顺序,工具容器负责能力。第二,为什么后面的架构、排查和优化都围绕「顺序」和「重复」展开,而不是围绕「功能有没有」。

一个必须说清的边界:Harness 具体在哪些切点暴露钩子、每个能力的默认开关如何,需按当前官方文档与 v2.0.3 源码核验,本文不把未核验的细节写成结论。

包装非升级
循环仍如旧
装配归一后
能力可插拔

04、架构

[输入] LiveKit 会话事件 / 用户文本
    |
    v
[模块] HarnessAgent(包装 ReActAgent + Middleware 链 + Toolkit)
    |
    v
[数据/状态] Workspace / Memory / Compaction 状态
    |
    v
[处理] ReAct 循环 + 中间件前后钩子(权限、工具、Skill、Plan)
    |
    v
[输出] 文本结果经 Bridge 回推 LiveKit 房间

边界:LiveKit 只管 WebRTC 房间与实时音视频传输;Realtime Bridge 只做媒体与消息适配,保持最薄;Agent 的推理、工具、状态、压缩、技能、计划、子代理全部由 AgentScope Java 侧承担。HarnessAgent 位于 AgentScope 内部,不跨到传输层。

收益:装配顺序从业务代码移到框架管线,加能力的改动面从「runtime 多段」收敛到「构建入口一处」;能力默认组合有统一来源,review 时可以直接对照官方文档。

代价:调试路径变深。以前断点打在 new ReActAgent 那一行,现在要先理解中间件链的插入顺序,再定位到具体切点。另外,框架默认策略会覆盖一部分自定义,需要显式确认哪些默认可以接受。

适用条件:能力数量超过三四个、需要长期演进、团队不止一人维护同一段装配代码。

不适用条件:只有一两个工具、无状态、一次性脚本或 PoC——这时候 Harness 的收益抵不上理解成本,手工装配反而更透明。

涉及框架行为的结论,落脚点如下:架构与装配顺序见 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/docs/v2/zh/docs/harness/architecture.md ,HarnessAgent 的字段、构建入口与包装方式见 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java 。本文实验按 v2.0.3 复现;写作当天最新正式版请以 https://github.com/agentscope-ai/agentscope-java/releases 为准,本文不对最新版号做断言。

输入是会话
中间是管线
输出回房间
边界须写死

05、实战一次

以下代码与命令未在当前环境实测,给的是预期形态;builder 方法名、包名与依赖坐标请以 v2.0.3 源码为准。

第一步,从上一章分支继续创建本章分支:

git checkout chapter/15-issue-pr
git checkout -b chapter/16-harness

第二步,确认依赖坐标。harness 模块坐标请直接查教程仓库与 v2.0.3 源码中的 pom,不要凭记忆写:

grep -rn "agentscope-harness" ./pom.xml ./**/pom.xml

预期在运行时模块中引入(版本与 groupId 以上一步结果为准):

<dependency>
  <groupId>io.agentscope</groupId>
  <artifactId>agentscope-harness</artifactId>
  <version>2.0.3</version>
</dependency>

第三步,迁移装配层。工具注册逻辑原样保留,只换宿主:

public final class AvatarRuntimeV2 {

    private final AvatarProjectService projectService;
    private final ModelRouter modelRouter;
    private final McpClientRegistry mcpClients;
    private final Path workspaceRoot;

    public AvatarRuntimeV2(AvatarProjectService projectService,
                           ModelRouter modelRouter,
                           McpClientRegistry mcpClients,
                           Path workspaceRoot) {
        this.projectService = projectService;
        this.modelRouter = modelRouter;
        this.mcpClients = mcpClients;
        this.workspaceRoot = workspaceRoot;
    }

    public HarnessAgent build(AvatarProject project) {
        return HarnessAgent.builder()
                .name(project.getAgentName())
                .model(modelRouter.forName(project.getModel()))
                .systemPrompt(project.getSystemPrompt())
                .toolkit(buildToolkit(project))
                .workspace(workspaceRoot.resolve(project.getId().toString()))
                .build();
    }

    private Toolkit buildToolkit(AvatarProject project) {
        Toolkit toolkit = new Toolkit();
        toolkit.register(new ProjectCrudTools(projectService));
        toolkit.register(new McpToolkit(mcpClients));
        return toolkit;
    }
}

注意这里删掉了三样东西:手工 new 的 Memory、手工挂在构造处的权限中间件、以及散落的能力开关。删得对不对,不靠感觉,靠第 06 章的排查证据。

第四步,启动与请求。Bridge 侧调用路径保持不变,只是注入的 Agent 变成 Harness 产物:

HarnessAgent agent = runtime.build(project);
String reply = bridge.ask(agent, sessionId, userText);

第五步,回归验收。用例清单不新增,全部复用前十几式已经写下的核心用例,逐条在 chapter/16-harness 分支上重跑:项目信息查询、数字人开场白与结束语、权限拦截、MCP 工具调用。四条全部通过才允许提交。

第六步,提交:

git add -A
git commit -m "refactor(ch16): migrate runtime to HarnessAgent"

验收的第二件事,是列出一张清单:Harness 自动提供了什么。按官方架构文档与 HarnessAgent 源码梳理,至少包括这些方向(具体开关与默认值需按 v2.0.3 源码核验):

能力 迁移前 迁移后
ReAct 推理循环 手工装配 Harness 包装 ReActAgent
工具注册与分发 业务 runtime Toolkit + Harness 装配
中间件管线与顺序 业务 runtime 决定 Harness 统一编排
Workspace / Filesystem 无或自建 Harness 提供
Memory 手工注入 Harness 装配
Compaction 上下文压缩 手工挂载 Harness 装配
Skill 加载 分支判断 Harness 装配
Plan Mode 分支判断 Harness 装配
Sandbox 手工接入 Harness 装配
Subagent 手工创建 Harness 装配
MCP 接入 手工注册 经 Toolkit 接入

这张表本身就是本章的交付物:迁移之后,业务代码只回答「用哪些工具、给什么提示词、工作目录在哪」,其余问题由框架回答。

先建新分支
再换装配层
工具仍原地
权限不放手

06、排查

第一条证据链:迁移后工具像「不存在」。

现象:迁移完成后,数字人回答「我无法查询项目信息」,而运行日志里没有任何工具调用记录。

怀疑:第一反应是模型变弱了,或者 systemPrompt 被覆盖。

检查:按顺序看三件事——Toolkit 里实际注册了几个工具、HarnessAgent 构建时 Toolkit 是否被真正接收、请求到达模型时工具描述是否出现在上下文中。

证据:对照 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java 的字段与构建入口,确认工具必须注册进 Harness 实际持有的那个 Toolkit 实例。迁移时如果一边建 Toolkit、一边又走了旧的传递路径,就会出现「工具建了但没被接住」。

错误尝试: 第一轮修复选择了在 systemPrompt 里加一句「你必须调用工具查询项目信息」。这是错的。工具能不能被模型看见,由 Toolkit 到推理上下文的传递决定,不由提示词的真实性决定;提示词只会让模型在不存在的工具上编造一次调用,从而把「工具没接住」伪装成「模型不听话」,浪费一轮排查。

根因:装配入口换层时,工具注册的对象与 Harness 消费的对象不是同一个。

修复:统一在 buildToolkit 里构造 Toolkit,并只通过 HarnessAgent 构建入口传入,删掉其余注册路径。

第二条证据链:对话历史重复,且长会话内容莫名丢失。

现象:迁移后同一轮问答在历史里出现两份;稍长的会话里,早期内容会消失。

怀疑:前端重复发送消息,或 Bridge 重试导致重复写入。

检查:先看 Bridge 的重试日志(无重复发送),再检查运行时是否同时存在两套记忆来源。

证据:Harness 侧自带 Memory 与上下文 Compaction 装配;迁移时如果保留手工 new 的 Memory 再注入,同时 Harness 又装配了默认记忆与压缩,就会出现两份历史,以及压缩策略各算一次。

根因:迁移只做了「加」,没做「删」,形成能力重复。

修复:移除手工 Memory 与手工压缩挂载,只保留 Harness 装配;如果确实需要自定义策略,改为在 Harness 管线上替换对应单元,而不是并列第二套。

上游贡献判断: 目前观察到的是文档与 API 理解成本问题(构建入口、默认开关、装配顺序的说明密度不足),不是可在最小 Demo 复现的功能缺陷;v2.0.3 上复现的是理解偏差而非错误行为,main 分支是否已有变化需按当前源码与 Release 核验;是否已有相关 Issue/PR 需现场搜索 https://github.com/agentscope-ai/agentscope-java/issues 与 https://github.com/agentscope-ai/agentscope-java/discussions 后才能判断,当前只能记为候选,不构成已提交的贡献。

现象先复现
证据再落位
猜测最耗时
根因只一条

07、优化

按第 06 章的两条根因,V2 的修改只有三处,其余代码不动。

第一处,装配入口唯一化:删除 AvatarRuntime 里所有独立的 Toolkit、Memory、压缩挂载路径,只保留一个 build 方法。原因是双入口必然导致「谁生效」不可判定。新行为是:运行时只有一个 Agent 构建点,Harness 管线内的顺序由框架决定。验证方法是搜索装配相关关键字,确认全仓库只剩一处构建调用。

第二处,能力开关外置:把「这个项目是否启用 Plan、是否挂载 Skill」从运行时 if 改成项目配置字段,构建时一次性读入。原因是开关散落在运行分支里,回归时无法枚举组合。新行为是:组合空间可枚举,用例可以按组合覆盖。验证方法是列出配置组合与对应用例的对照表。

第三处,权限保留在 Harness 管线上:权限中间件不删,改为按 Harness 的中间件接入方式挂载,保持与迁移前相同的拦截语义。原因是安全语义不能因为迁移而放松。验证方法是用一条必然被拒的请求,确认拦截原因与迁移前一致。

不虚构验证数据:以上三步的验证方式都是可执行的检查动作,实际通过与否要在自己的分支上跑完核心用例后填写,本文不代替你的运行结果。

删掉重复的
留下必须的
收拢注册口
再跑一遍测

08、演进

[同一输入] 运行页 /run/{projectId} 的一次问答
    |
    +--[V1] 手工装配 ReActAgent
    |      代价:装配顺序隐式、开关散落、回归边界模糊
    |
    +--[V2] HarnessAgent 统一装配
    |      代价:调试路径变深、依赖官方默认策略
    |
[Trade-off]
得到的是装配顺序有唯一来源、加能力改一处;
失去的是对每一层挂载位置的直接控制;
适用边界是能力多项、长期演进、多人维护的运行时。

比较五个维度。正确性:V2 的关键风险不是算错,而是能力重复导致语义漂移,必须靠回归用例守住。稳定性:V1 的稳定性依赖作者记忆,V2 的稳定性依赖框架版本,因此版本锁定更重要。复杂度:V1 是代码复杂度高、认知复杂度低;V2 相反。成本:V2 前期要读文档与源码,后期每次加能力更便宜。适用范围:V2 适合能力成体系的数字人运行时;单工具场景仍是 V1 更划算。

遗留问题有两个:一是可观测性,中间件链的执行顺序在日志里目前不可见,需要补结构化日志;二是版本耦合,框架升级会直接改变默认装配,需要把升级纳入回归计划。

旧路可控但重
新路统一但深
取舍写成表
边界才算清

09、洞见

9.1 反直觉判断:Harness 装得越多,你越需要先定义边界

能力被自动装配后,最容易出错的不是「没装上」,而是「装上了但你不知道」。第 06 章第二条证据链就是典型:默认记忆与手工记忆同时存在,功能看起来正常,语义已经变了。能力越多,越要先写清楚哪些交给框架、哪些必须自己管。

9.2 反直觉判断:迁移的最大风险是能力重复,不是功能缺失

功能缺失会立刻报错,能力重复不会。重复的 Memory、重复的压缩、重复的中间件,表现为「偶尔不对」,排查成本远高于一次启动失败。所以迁移的动作清单里必须有一列叫「删什么」,而不是只有「加什么」。

9.3 装配权交出去,调试权要自己拿回来

换装配层不能顺手把可观测性也交出去。迁移的同时至少要保证三样可见:本轮用了哪些工具、中间件按什么顺序执行、压缩是否触发。否则下一次线上问题会卡在没有断点可打的位置。

9.4 什么时候不应该用本章能力

只有一两个工具、没有状态、没有长会话、没有多轮技能切换的场景——例如一个只做文本润色的内部小工具——用 HarnessAgent 是过度装配:你会为了统一顺序付出读文档和源码的成本,而收益接近于零。还有一类不适用:能力边界尚未稳定、正在快速试错的探索期。装配顺序的价值来自「长期不变」,在能力还在天天换的时候,先把能力试清楚再收拢装配。

能力多一分
边界多一寸
迁移看重复
不看功能表

10、系统落地

原来有什么:一个能跑通 LiveKit 实时会话、具备工具调用与权限拦截的数字人 Demo,运行时的装配逻辑散在 AvatarRuntime 内部,能力清单只存在于代码与记忆里。

本篇新增什么:一个统一的 Agent 构建入口,Harness 管线承担 Workspace、Memory、Compaction、Skill、Plan Mode、Filesystem、Sandbox、Subagent、MCP 的装配;一张「Harness 自动提供什么」的对照表;一份迁移回归清单;一个长期保留的教程分支 chapter/16-harness。

现在能做什么:给数字人项目加一个新能力时,先问它在 Harness 里有没有对应单元,而不是先改 runtime;回归时按用例清单跑,不靠通读装配代码推断影响面。

还缺什么:中间件执行顺序的观测能力;Harness 版本升级的回归机制;以及跨项目(多租户)场景下 Workspace 隔离的验证——后者属于后续章节范围,本篇不展开。

下一步如何演进:把本章的迁移结果作为后续所有能力章节的宿主基线,任何新能力都优先走 Harness 装配路径;如果确实需要自定义,也是在管线上替换单元,而不是在旁边再挂一套。

开源参与点:本章未发现明确上游问题。第 06 章记录的两处现象均可在最小 Demo 中复现为理解偏差,而非框架缺陷;文档密度不足属于体验类问题,可作为讨论或文档 PR 的候选,但在搜索官方 Issues、Discussions 并确认没有重复条目之前,不做任何提交动作。

宿主已换代
工具仍原样
缺的是观测
下一步补它

11、小结

Q1 → 手工装配顶不住的地方不是功能,而是顺序与开关没有唯一负责人
Q2 → 该保留的是工具注册与权限语义,该交出去的是能力挂载与顺序编排
Q3 → 直接把 ReActAgent 换成 HarnessAgent 不够,必须同步清理重复能力与统一入口
状态 → chapter/16-harness 分支上,运行时装配收敛为单一 HarnessAgent 构建入口,工具与权限保留,核心业务用例可回归

本章真正可交付的不是一段新代码,而是一条判断:装配顺序是设计资产,它应该有唯一来源。交接完成后,后续章节的增长点从「往 runtime 加代码」变成「在 Harness 上换单元」。

问题有答案
状态可交付
分支已就位
下一式继续

12、作业

12.1 理解题:HarnessAgent 与 ReActAgent 的关系是什么,为什么说换掉的是装配权而不是推理引擎?

参考答案:HarnessAgent 在外层,包装并持有 ReActAgent,推理循环仍由 ReActAgent 承担;Harness 负责把 Workspace、Memory、Compaction、Skill、Plan、Sandbox、Subagent、MCP 等能力按统一顺序装进 Middleware 管线,并通过 Toolkit 接入工具。因此迁移改变的是「谁负责装配与排序」,不是「谁负责思考」。答这道题不能只凭印象,建议打开 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java ,看它如何引用与构造 ReActAgent。

12.2 实战题:在 chapter/16-harness 分支上完成迁移,并产出两张清单。

参考答案:一张是回归清单(项目信息查询、开场白与结束语、权限拦截、MCP 调用,逐条跑通);一张是 Harness 自动能力清单(按第 05 章表格逐项核对你自己的项目实际命中了哪些,未命中的注明原因)。提交信息使用 refactor(ch16): migrate runtime to HarnessAgent。注意:不要在本分支上引用任何第三方式的自定义扩展绕开 Harness 装配路径,否则清单不可信。

12.3 排障题:迁移后工具调用消失,你会先看哪个环节,为什么不能先改提示词?

参考答案:先看 Toolkit 的实际注册对象与 HarnessAgent 构建入口是否指向同一实例,再看工具描述是否进入模型上下文。改提示词之所以错误,是因为工具可见性由装配决定,提示词只能诱发模型对不存在的工具做无效调用,把「工具没接住」伪装成「模型不听话」。如果排查后怀疑是框架侧行为,请先搜索官方 Issues 与 Discussions:https://github.com/agentscope-ai/agentscope-java/issues 。

12.4 架构判断题:什么情况下应该拒绝使用 HarnessAgent,坚持手工装配?

参考答案:能力只有一两个、无状态、无长会话、无技能与沙箱需求、且短期内不会扩展时,Harness 的统一编排带来的收益小于理解与版本耦合成本。另一种是探索期:能力边界尚未稳定,此时收拢装配会把不确定性固化进框架默认值。判断标准不是「框架有没有这个能力」,而是「装配顺序是否长期稳定、是否需要多人共同维护」。

做题要动手
源码是答案
回归不放过
判断题最难

13、思考

回到本篇的核心冲突:装配权该留在业务代码,还是交给框架?结论不是简单的「交给框架更好」,而是「装配顺序必须有唯一来源」。当能力只有两三个,唯一来源可以是你自己写的那二十行;当能力成体系、又要在多人之间交接,唯一来源就应该是一层被官方维护、可被文档描述的装配管线。

这条判断可以复用到任何框架迁移上:迁移前先列「删什么」,再列「加什么」;先跑通回归,再谈收益;接受默认策略之前,先确认自己知道默认值是什么。

「会用框架」是照着文档把 API 调通;「能参与框架演进」是在读懂装配顺序之后,判断哪些默认该被质疑、哪些缺口值得提一个 Issue 或一段文档 PR。这两者之间,隔着的正是本章读的那一份 architecture.md 和那一个 HarnessAgent.java。

会用框架者
知其装配序
能参演进者
识其边界线

posted @ 2026-10-11 11:14  李福春  阅读(7)  评论(0)    收藏  举报