「一切皆插件」在 Java 企业栈怎么落地?拆解太一企业版的 SPI、三重闸门与治理链

技术细节均来自源码实测,核验于 2026 年 8 月 16 日。
姊妹篇(面向央国企决策者的版本):《央国企的智能体底座,为什么必须「一切皆插件」》。这一篇是给写代码的人看的。
产品官网:mate.vip/ee

目录


一、先说清楚这篇要解决什么问题

做企业 AI 平台的人早晚会碰到同一个局面:一个集团,二三十家二级单位,每家要的功能面都不一样。有的要合同审核,有的只要 AIOps,有的因为数据出境的事连模型通道都得单独一套。

传统解法是拉分支。一个基线拉 28 个分支,改一处推 28 次,半年后没人说得清哪个分支上跑的是什么。

理想解法是一套代码加 28 张装配单。

这中间的差距不是「多写点配置」能补上的,它是架构问题。这篇文章把太一企业版(工程代号 MateHive Pro,Java 21 + Spring Boot 4.0 + Spring AI 2.0,97 个 Maven 模块)里跟这件事相关的设计逐个拆开讲,包括为什么这么做、以及不这么做会踩什么坑。

想直接抄设计的,可以跳到第六、七、九节,那三节是全篇密度最高的。


二、DeepSeek Harness 给了一个参照系

8 月 13 日 DeepSeek 开源了 DeepSeek Harness(简称 dsh),一套插件化的智能体运行时。我 8 月 16 日拉了一次 GitHub API:116,283 star、11,368 fork,距仓库创建 62 小时。MIT 协议,TypeScript。

在这里插入图片描述

它值得一看的地方在于把「一切皆插件」做到了一个挺极端的程度:连 agent 的主循环本身都是能整体替换的插件,扩展包只依赖抽象接口。仓库里反复出现的一个模式叫 capability seam(能力接缝),由三个角色构成:

角色职责
Service Definition只定义「这个能力长什么样」,不含实现
Service Provider可插拔实现,同一时刻挂一个
Consumer只认接口,不知道背后是谁

这样的三件套在 dsh 仓库里有三十多处。文件系统、命令行、子智能体、网页访问都是这个结构。

这套模式不新,Java 生态里它就叫 SPI。但把它作为整个产品的组织原则而不是某个模块的局部技巧,是另一回事。太一走的是同一条路,只是落在 Spring Boot 的条件装配体系上。

需要说清楚边界:dsh 是面向开发者的单机运行时,没有租户、没有 RBAC、没有审批流、没有国密、没有成本核算,社区反馈里产品完成度和架构强度也明显不在一个水平线上。拿它直接上生产等于住毛坯房。下面讲的是同一套哲学落到企业合规面上要付出什么。


三、太一的分层:内核 + 能力 starter + 场景包

先看物理结构:

mate-hive/
├── mate-hive-core/            扩展点 SPI + 默认实现(= 基础形态的能力面)
│   ├── spi/                   143 个扩展点契约文件
│   ├── model/                 框架无关值对象(record)
│   ├── support/               @ConditionalOnMissingBean 的默认实现 + 治理链
│   └── config/                HiveCoreAutoConfiguration
├── mate-hive-starters/        37 个能力 starter,丢 jar 即点亮,拔 jar 即降级
├── mate-hive-scenarios/       9 个场景包,纵向切片,只依赖 core SPI
└── mate-hive-app/             启动壳(9070):组装 core + starters + 场景包

一句话总纲:同一份核心代码,装哪些 starter 决定交付出来的是什么形态。

在这里插入图片描述

37 个能力 starter 是横向能力(审计、护栏、知识库、记忆、沙盒、渠道、工作流、信创……),9 个场景包是纵向业务切片(合同审核、招投标、制度问答、公文写作、AIOps、问数、方案智撰、财务、金融投资)。两者的区别在依赖方向:场景包只依赖 core SPI,不依赖任何 starter,所以它能被单独摘掉。


四、可插拔的前提:core 的 pom 里没有 Spring AI

这一节是全篇最容易被跳过、但最要命的一条。

mate-hive-core 的 pom 里只有四个必需依赖:

mate-base
reactor-core
slf4j-api
spring-boot-autoconfigure

另有三项标了 <optional>true</optional> 不传递:servlet-api、jackson-databind、spring-webmvc。

没有 Spring AI,没有 MyBatis,没有 Dubbo。

为什么这条是前提?因为只要 core 依赖了 Spring AI,那么「不装 AI 能力」这个形态就不存在了——jar 在 classpath 上,类会被加载,自动配置会被触发,你能做的只剩下加开关。而开关关掉的东西,代码还在、依赖还在、攻击面还在。

反过来,core 是纯契约层,它对「谁来实现」一无所知,于是拔掉任何一个 starter 都不会让 core 编译不过、也不会让服务起不来,最多是那条能力线回落到默认实现。

这条边界不是靠自觉守的,仓库里有一个阻断级的 CI 检查:core 包里只允许 import vip.mate.hive.core.*,出现任何 vip.mate.hive.<其它> 就红。

如果你也在做类似的分层,这条建议先做:给内核包写一条 import 白名单检查,接进 CI。它比任何架构文档都有效,因为文档拦不住赶工期的人,CI 能。


五、扩展点 SPI:什么该进 core,什么该留在 starter

mate-hive-core/src/main/java/vip/mate/hive/core/spi/ 下现在有 143 个文件:118 个 interface、13 个常量/异常 class、11 个 record、1 个 enum

最早立的是九个核心扩展点,至今没变:

AgentRuntime            编排入口
AgentExecutionFilter    治理链挂载点
ToolGuardPolicy         工具准入
AuditPort               审计
RetrievalPort           检索
MemoryLifecycle         记忆
CryptoProvider          加解密 / 签名
DesensitizePort         脱敏
ChannelConnector        渠道接入

这九个是唯一「拔掉对应 starter 会整条能力线降级、但服务照常启动」的一组。其余 100 多个是后来按域长出来的:编排与运行时 37 个、治理与安全 18 个、知识与检索 18 个、智能体资产与技能 13 个、审批与 HITL 12 个、会话与渠道 12 个、组织与工作区 12 个、产物与场景 11 个、记忆 10 个。

判据只有一条

接口该不该进 core SPI,实际执行的判据就一条:契约要跨模块成立——core 里的默认实现或治理链要调它,而实现方在另一个 jar 里。

典型例子是 SandboxExecPort,它有三个实现方:core 里的禁用实现、sandbox-starter 的本地/容器实现、app 壳里的远程转发实现。再比如 DatabaseQueryPort 声明在 core、实现在问数场景包里。

反过来,变化点只在一个 starter 内部打转的,一个都别进 core。这一侧的量比 SPI 大得多:

starter内部 public interface 数是否进 core
persistence-starter1210
knowledge-starter27(分片策略、文档解析器、图存储、三元组抽取…)0
channel-starter230

判据反过来用同样成立:如果一个接口进了 core SPI 却只有一个实现方、而且实现方永远是同一个 starter,它就该退回去。core 每多一个符号,基础形态的编译面和交付时的解释成本就多一分。

这条我见过太多项目做反:把所有接口一股脑塞进 common,最后 common 变成了谁都得依赖的巨型包,可插拔就无从谈起了。


六、三重闸门与 marker 类模式

企业能力靠三道闸装配,顺序是先类、再属性、最后授权,越靠前越硬:

注解拦在哪拔掉之后
① jar 在不在@ConditionalOnClass(XxxMarker.class)classpath 类加载整个自动配置类不触发,@Bean 方法一个都不解析
② 开关开没开@ConditionalOnProperty配置属性类不装配;同一份镜像靠 .env 就能关掉一条能力线
③ 授权给没给@ConditionalOnLicense("feature-code")授权判定只有被标注的那个 @Bean 不装配,其余照常

第三档的语义值得单独强调:缺授权的表现不是整个 starter 消失,而是那一个高阶 bean 不装配、回落 core 默认实现。也就是说功能还在,只是用基础实现跑。这个语义对商业交付很关键,页面不会 500,只是能力弱一档。

marker 类模式

每个受闸 starter 会带一个空的 final 类,唯一用途就是被 @ConditionalOnClass 引用:

package vip.mate.hive.xinchuang;

/** {@code @ConditionalOnClass(XinchuangProMarker.class)} 的存在性标记。jar 在即候选。 */
public final class XinchuangProMarker {
    private XinchuangProMarker() {
    }
}

为什么不直接引用一个真实的业务类?因为真实类会随重构改名、移包,而闸门一旦引用了它,重构就会静默改变装配行为——类找不到了,@ConditionalOnClass 判 false,整个 starter 悄悄不装配了,编译还是绿的。marker 是专为闸门存在的稳定符号,不参与任何业务演进。

这是个很小的技巧,但它把「重构导致装配漂移」这类最难查的问题从根上掐掉了。


七、装配顺序:@ConditionalOnMissingBean 和 before 到底怎么配合

这一节讲清楚一件事:企业实现怎么在不改一行核心代码的前提下覆盖 core 默认实现。

机制其实很朴素,但要点在于顺序。

core 的每个默认实现都标了 @ConditionalOnMissingBean。而 @ConditionalOnMissingBean 的判定只看此刻容器里已注册的 bean 定义。所以企业自动配置必须先跑:

@AutoConfiguration(before = HiveCoreAutoConfiguration.class)

企业 bean 先注册,轮到 core 时发现「已经有了」,默认实现自动让位。企业闸门任一不成立,core 默认照常注册。核心代码零改动。

一个真实的配置类,这是最标准的配方:

@AutoConfiguration(before = HiveCoreAutoConfiguration.class)
@ConditionalOnClass(ToolGuardProMarker.class)
@ConditionalOnProperty(prefix = "mate.hive.toolguard", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(ToolGuardProperties.class)
public class ToolGuardProAutoConfiguration {

    /** 策略引擎守卫,仅在授权时覆盖默认实现。 */
    @Bean
    @ConditionalOnLicense("toolguard-pro")
    @ConditionalOnMissingBean(ToolGuardPolicy.class)
    public ToolGuardPolicy proGuard(PolicyRepository repository, ToolGuardProperties properties) {
        return new PolicyEngineGuard(repository, properties.getDefaultEffect());
    }

    /** 把当前 ToolGuardPolicy(企业实现或回落的默认守卫)接入治理链。 */
    @Bean
    public AgentExecutionFilter toolGuardFilter(ToolGuardPolicy policy) {
        return new ToolGuardFilter(policy);
    }
}

注意这两个 @Bean 的差别:proGuard 受授权闸控制,toolGuardFilter 不受。所以无论授权如何,过滤器都会入链,只是它拿到的策略实现不同。治理链的完整性和能力的强弱是两件事,不能混在一个闸门里

另外一个容易读错的地方:不是所有 starter 都需要 before。全仓 37 个 starter 里只有 13 个用了它,其余的只是新增能力,不覆盖任何默认实现,压根不需要抢跑。加了反而会让装配顺序图变复杂。


八、治理链:四个常量定死的顺序

工具执行前后的治理是一条固定顺序的过滤器链。顺序写在常量类 FilterOrder 里,一共就四个常量:

常量归属 starter
FilterOrder.GUARD20toolguard
FilterOrder.AUDIT30audit
FilterOrder.IDEMPOTENCY35cluster
FilterOrder.DESENSITIZE40xinchuang
工具调用 → ToolGuardFilter(20) → AuditFilter(30) → [IdempotencyFilter(35)] → DesensitizeFilter(40) → 真正执行
             谁能用 / 参数约束      白盒审计 + 摘要签名      幂等去重 / 回放           国密 + 出域脱敏
             外部域名 → HITL

各 starter 注册 AgentExecutionFilter 时必须取这些常量做 getOrder() 返回值,不允许自己拍数字。

幂等为什么卡在审计后面

这是个有意的设计。幂等命中缓存要短路真实执行,如果它排在审计前面,短路的那次调用就没有审计记录了。排在审计之后,动作已经由审计过滤器在 beforeTool 记下,短路回放不漏审计

before 顺序、after 逆序

编排器的核心逻辑:

for (AgentExecutionFilter filter : filters) {          // 守卫 → 审计 → 幂等 → 脱敏
    FilterResult fr = filter.beforeTool(current, ctx);
    if (fr.isReplay()) { replay = fr.replayResult(); break; }     // 幂等短路,但 after 仍全跑
    if (!fr.isProceed()) { throw new GovernanceException(...); }  // DENY / REQUIRE_APPROVAL
}
ToolResult result = replay != null ? replay : executor.execute(current);
for (int i = filters.size() - 1; i >= 0; i--) { ... }   // 逆序

after 逆序不是为了对称好看:脱敏要在最贴近出域的地方先改,所以它在 before 里排最后、在 after 里排最先。

链在构造时排一次序并 List.copyOf 冻结,之后不可变。链的实际构成随时可查,GET /api/v1/hive/edition 会返回当前链的描述符,形如:

["HiveLogContextFilter@-2147483648", "ToolGuardFilter@20", "AuditFilter@30", "DesensitizeFilter@40"]

打头那个不参与裁决,只把 runId / agentId / conversationId 绑进日志上下文。它站最前是为了让守卫、审计、脱敏自己打的日志也带上 runId。

顺带说一句,把「当前装了哪些治理过滤器」做成一个可查询的运行期端点,比翻部署文档靠谱得多。交付验收的时候这一个端点能省掉半天扯皮。


九、GovernedToolCallback:Spring AI 的工具循环为什么绕不过去

这是全篇我最想让人看的一节。

问题

Spring AI 的 ChatClient 拿到 ToolCallback 之后,工具调用循环是它自己内部驱动的:模型返回 tool_call,框架执行工具,把结果塞回消息,再调模型,全程在 Spring AI 的循环里。

如果你的治理逻辑写在「自己的编排代码」里——比如在调用 ChatClient 之前先检查一遍——那么模型每一次自主发起的工具调用都是从治理链旁边溜过去的。

这不是理论风险。治理链管的是越权拦截、审计留痕和出域脱敏,漏一次就是一次合规事故。而且这种漏法特别隐蔽:功能测试全过,日志里也有东西,只是少了一部分。

解法

不去改 Spring AI 的循环,而是在把工具交给 ChatClient 之前逐个包装。

GovernedToolCallback 实现 ToolCallback 接口,对外和原工具一模一样,call() 内部先过治理链再落到真实工具:

public class GovernedToolCallback implements ToolCallback, ProvenanceAware {
    private final ToolCallback delegate;
    private final AgentExecutionChain chain;
    private final AgentContext ctx;      // 绑定本次请求的主体,治理判定能感知分权分域
    // …另有十余个字段:审批队列、结果长度上限、超时、金库、来源化、
    //   拦截器微链、指标、准入策略、失败提示、重试策略
}

于是包装点就是唯一入口。LLM 循环仍然由 Spring AI 驱动,但循环内每一次工具执行都在治理链里。能力层(编排)和治理层(合规)在这一个点上融合,谁也绕不开谁。

一条维护上的硬约束

生产代码里 GovernedToolCallback 的构造点只有一处:运行时组装工具清单的那个 stream,把每个 ToolCallback 逐个 map 成 GovernedToolCallback,再链式挂上拦截器、指标、准入策略等等。其余几十处构造全在测试目录下。

所以改工具装配路径的时候,必须确认新路径也走这一处包装。否则新加的工具就是治理链外的裸调用,而且从表面看不出来。

这条约束值得写进团队的 review 清单。


十、轮级扩展链 TurnAdvisor 和那段禁区

治理链管的是工具执行这一层。每一轮对话的装配(改 system/user 消息、注入记忆引导、RAG 接地、历史压缩、用量记账)是另一层,走 Spring AI 的 Advisor 机制,在 hive 里用一个标记接口 HiveTurnAdvisor 分组。

排序契约在 TurnAdvisorOrder。理解它得先知道 Spring AI 的两个锚点:ChatMemory advisor = HIGHEST_PRECEDENCE + 200ToolCallingAdvisor.DEFAULT_ORDER = HIGHEST_PRECEDENCE + 300。Spring 按 order 升序执行,越小越外层。

段位语义
BASEHIGHEST_PRECEDENCE + 100循环基准。内建轮级 advisor 全落在 [BASE, BASE+40],恒小于 +200/+300,因此只在进工具循环前装配一次
TRACE / HISTORY / MEMORY / GROUNDING / INBOX / AT_PATHBASE + 0/10/20/30/35/40六个具名段位
RESERVED_BAND_START ~ END+200 ~ +300禁区,外部 advisor 落进来一律拒绝入链
LOOP_INNER+400循环基准,对每一次循环内模型调用都生效
USAGE_LEDGERLOOP_INNER + 10用量记账,最内层紧贴模型调用

两个设计点值得抄。

第一,那段禁区。 落在 [+200, +300] 的 advisor 会与 ChatMemory 和 ToolCalling advisor 交织,结果既不是「进循环前装配一次」也不是「每轮都跑」,是一种谁都不想要的中间态。与其等着别人踩,不如直接在入链时判定并拒绝。常量类里有个静态方法 inReservedBand(int) 做闭区间判定。

第二,用量记账为什么必须在最内层。 工具循环下,调用方最终只拿到最后一轮ChatResponse。不逐轮记账,前 N-1 轮的 token 就全漏了,计费口径直接错。它只读响应不改消息,所以放最里面是安全的。

这个坑挺隐蔽的:功能一切正常,只有账单对不上。

段位常量有 11 个,落在段位上的内建实现是 9 个。顺序也不是随手排的,举两个例子:记忆引导必须排在接地之前(保住 system 前缀字节不变,缓存才命中),@路径展开必须排在接地之后(接地会重建用户消息,附件得在重建之后追加才不被覆盖)。


十一、UI 也插拔:menu-manifest.yml 的声明式对账

拔掉 jar 但菜单还在,用户点进去 404——这是能力可插拔做了一半最常见的形态。

太一的做法是让菜单跟着 jar 走。每个 starter 内置一份 menu-manifest.yml,服务启动时由 MenuAutoRegistrar 聚合 classpath 上的全部清单,经 Dubbo 幂等注册到 mate-system,再按模块码做声明式对账:本次没声明的节点一律删除。

结果就是拔掉 jar 菜单跟着消失,功能面和部署形态始终是同一本账。

8 月 12 日实测:38 份清单自注册出 49 个页面菜单和 73 个按钮级权限点。这张表既是功能清单,也是部署形态清单。

做过交付的应该能体会这条的价值。传统做法里,「这个功能这次不上」意味着前端注释一段路由、后端加个 if、验收时靠人记着别点那个按钮,三个月后没人记得。现在是不装那个 jar,菜单自己就没了。

一个提醒:自注册时只自动授予平台超管角色,其余角色要在角色管理里显式勾选权限码。菜单出现不等于当前登录人看得到,排障时容易绕远路。


十二、多租户不是靠人记住的

三条正交的隔离轴:租户是硬边界,工作区是租户内的协作单元,部门管数据权限。

有这三个概念不稀奇。稀奇的是它被机器校验着——/api/v1/hive/** 下每个端点都必须用 @HiveTenantAccess 声明自己在这三轴上的姿态。

仓库里有一批约束型测试,用测试当机器校验,扫全 classpath 断言架构不变式。最有代表性的是 HiveWriteEndpointAnnotationTest

  • 扫描 vip.mate.hive 下所有 @RestController,断言写端点必须标注 @HiveTenantAccess
  • 同时反向断言豁免清单里不含已失效条目

两个方向都断言,意味着加漏了会红,清单腐化了同样会红。同类的还有免登录端点清单一致性、免登录端点的网关可达性、技能披露门枚举完整性等等。

这个模式我强烈推荐。架构规范写进文档,三个月后一定破;写成一个扫 classpath 的测试,破了当场就红。成本是一个测试类,收益是一条永远不会腐化的边界。


十三、信创:换一个 CryptoProvider 的事

这一节是能力接缝价值最直白的一次演示。

信创能力是一个独立 starter,走标准三重闸门,默认关闭:

  • 不装或不开:平台用 JDK 标准算法实现 JdkCryptoProvider
  • 装上并开启:自动换成 GmCryptoProvider,SM2 / SM3 / SM4 全套,数据加密走 SM4,审计签名走 SM3 摘要加 SM2 签名
  • 上层代码一行不改

然后是最漂亮的那一下,源码文档里管它叫「组合红利」:

信创和审计是两个独立 starter。装上信创之后,审计 starter 的摘要签名自动切到国密,因为审计只依赖 CryptoProvider 这个 SPI,谁提供实现就用谁。两个 starter 互相不知道对方存在。

审计模块的代码里,没有一个字符提到国密。

这就是信创改造的正确姿势:不是把国密塞进每个模块,是往接缝里换一个插头。反过来,如果你的项目做信创改造需要全局搜索替换加密调用,那说明缺的不是国密库,是这层抽象。

沙箱侧同理,容器形态由一个配置项决定:

mate:
  hive:
    sandbox:
      container:
        kind: STRATOVIRT     # 通用栈用 DOCKER(runc / gVisor)
        pull-policy: never   # 离线内网

STRATOVIRT 走 iSulad 加 StratoVirt/Kata 微 VM。配套一组关不掉的硬约束:容器级断网、只读根文件系统、丢弃全部 capability、非 root 用户、内存 CPU PID 限额,应用层再叠墙钟超时、CPU 时间和输出截断。

一条交付现场的提醒:信创模式下 SM2 密钥对如果留空,系统会每次启动随机生成一对。重启之后公钥就变了,之前签出的审计签名再也验不了。要做长期可验证的审计链,生产必须显式配固定密钥对并纳入密钥备份。这种坑不会写在方案里,只会写在交付自检清单上。


十四、往里加东西的四条正道

这类平台最怕的是「加东西的姿势不统一」。太一把这件事收敛成四条路,选错了会写出拔不掉、也进不了交付形态的模块:

落点产物独立进程
① 业务微服务模块mate-biz/mate-{name}/可独立启动的 Spring Boot 应用
② 基础 startermate-starters/mate-{name}-starter/平台级通用能力 jar
③ hive 能力 startermate-hive/mate-hive-starters/hive 横向能力 jar
④ hive 场景包mate-hive/mate-hive-scenarios/hive 纵向业务切片 jar

走第一条的判据挺严:同时满足需要独立进程边界(独立端口、独立扩缩容、独立发版节奏)、有自己的库表和 Flyway 版本线、对外暴露 REST 或对内暴露 Dubbo 面。只是「一批新接口」或者「一个新表」,不要开新服务——开一个服务的成本是一个 JVM、一套 Nacos 配置、一条 CI 流水线、一份 compose 条目。

新增模块有 CLI:

java -jar mate-cli/target/mate-cli.jar new module mate-order --port 9060

生成 DDD 四层骨架、pom、启动类、application.yml、Flyway 初始迁移、menu-manifest.yml,并自动把 <module> 追加进父 pom。生成的配置里有三个旋钮已经接好了:

spring:
  application:
    name: mate-order
  cloud:
    nacos:
      discovery:
        metadata:
          gateway-path: /api/v1/order/**
mate:
  module:
    code: order
  • mate.module.code 让该服务的 Flyway 历史表变成 flyway_history_order,版本线彼此独立,不会撞车;
  • gateway-path 让网关从注册中心 metadata 自动建路由,新增服务不需要改网关一行代码
  • Nacos 的 import 段 dataId 必须逐环境字面写死,不能用 ${spring.profiles.active} 拼接——多 profile 会拼出非法 dataId,结果是基础设施配置整块丢失,而且报错并不直接。

DDD 四层的规矩:领域层零框架依赖;仓储接口在 domain、实现在 infrastructure;聚合根守护不变量;CQRS 读写分离不混用;对象转换一律走 MapStruct;领域事件经 DomainEventPublisher 端口发出。


十五、几条可以直接抄走的设计

这篇拆了不少东西,如果只带走五条,我会选这些:

1. 给内核包写一条 import 白名单检查,接进 CI。 分层能不能守住,靠的不是文档,是有没有人能提交一个破坏它的 PR 而 CI 是绿的。

2. 条件装配的 marker 用空的 final 类,别用业务类。 业务类一重构,闸门就静默失效,编译还是绿的,这类问题最难查。

3. 治理的完整性和能力的强弱分成两个闸。 过滤器该入链就入链,能力弱一档是另一回事。混在一个闸里,降级的时候治理会跟着一起没。

4. 如果你用 Spring AI 且有合规要求,去确认工具调用的包装点。 框架内部的工具循环是绕过你的编排代码的,包装 ToolCallback 是目前最干净的收口方式,而且构造点越少越好。

5. 把架构规范写成扫 classpath 的测试。 正反双向断言:加漏了要红,豁免清单腐化了也要红。

最后回到开头那个问题。一套代码加 28 张装配单,靠的不是某个神奇的框架,是把「这个能力装不装」这件事从代码分支挪到了装配层——挪的过程里,内核的依赖得干净、接口的归属得清楚、装配的顺序得明确、治理的入口得唯一。四件事缺一件,都会退回去变成拉分支。


参考资料

  • DeepSeek Harness 仓库:https://github.com/deepseek-ai/deepseek-harness(star 数据核验于 2026-08-16 10:03,仓库创建于 2026-08-13 19:56,均为北京时间)
  • Spring AI 2.0 Advisor 与 ToolCallback 文档
  • 太一企业版(MateHive Pro)源码与交付文档站,SPI 与 menu-manifest 数字实测于 2026-08-12
  • 产品官网:mate.vip/ee 商务与试用:微信 matecloud

太一企业版为商业授权软件,不提供开源发行版,功能面随授权与部署形态变化。本文对 DeepSeek Harness 的解读为第三方技术分析,非官方发布材料。文中数字会随开发漂移,以你核对时的源码为准。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐