Solon v4.1.0

harness - OpenAPI 业务接口接入

</> markdown
2026年9月7日 上午11:29:14

Harness 可以把 OpenAPI v2 / v3 文档描述的 HTTP 接口接入为 Agent 工具。需要区分两个概念:

  • apiServerAdd(name, source)name 是 Harness 构建期配置 Map 的键;
  • ApiSource.docUrlOpenApiGatewayTalent 的运行时管理键。

1、开启 OpenAPI 工具权限

当前工具权限枚举是 ToolName.TOOL_OPENAPI,实际工具名为 openapi

HarnessEngine engine = HarnessEngine.of("work", ".soloncode/")
        .sessionProvider(sessionProvider)
        .toolsAdd(ToolName.TOOL_OPENAPI)
        .build();

// 运行时动态授权
engine.allowTool("openapi");

新代码不要再使用旧的 REST API 工具枚举;AgentFactory 仍兼容旧字符串 restapi,但推荐统一使用 ToolName.TOOL_OPENAPI 或字符串 openapi

2、构建期静态注册

ApiSource source = new ApiSource().then(api -> {
    api.setDocUrl("https://api.example.com/v3/api-docs");
    api.setApiBaseUrl("https://api.example.com");
});

HarnessEngine engine = HarnessEngine.of("work", ".soloncode/")
        .sessionProvider(sessionProvider)
        .toolsAdd(ToolName.TOOL_OPENAPI)
        .apiServerAdd("orders", source)
        .build();

这里的 "orders" 只作为 HarnessOptions.apiServers 配置 Map 的键。引擎构建 OpenApiGatewayTalent 时遍历 Map 的 value,并通过 source.getDocUrl() 注册运行时 API 源;配置键 orders 不会传给网关,也不是 Agent 工具名。

因此,运行时查询、刷新和移除必须传 docUrl,不能传 orders

String docUrl = "https://api.example.com/v3/api-docs";

ApiSourceClient client = engine.getApiServer(docUrl);
engine.refreshApiServer(docUrl);
engine.removeApiServer(docUrl);

3、ApiSource 配置

ApiSource source = new ApiSource();
source.setDocUrl("https://api.example.com/v3/api-docs");
source.setApiBaseUrl("https://api.example.com");
source.addHeaderVar("Authorization", "Bearer ${token}");
source.addAllowedTool("getOrder");
source.addDisallowedTool("deleteOrder");
source.setTimeout(Duration.ofSeconds(30));
source.setAuthenticator(authenticator);
source.setEnabled(true);

主要字段:

字段说明
docUrlOpenAPI 文档地址;也是网关运行时 API 源键
apiBaseUrl实际业务接口基地址,可覆盖文档中的 server 地址
headers获取文档或调用接口时使用的请求头,可用 addHeaderVar 追加
allowedTools工具白名单;为空时不按白名单限制
disallowedTools工具黑名单,从候选接口中排除
timeoutHTTP 请求超时,类型为 Duration
authenticator自定义 ApiAuthenticator
enabled是否把该源的工具加入激活索引,默认 true

allowedTools / disallowedTools 用于裁剪最终激活的接口工具。修改运行时 Client 的过滤配置后,应刷新对应 docUrl,使网关工具索引重新同步。

4、运行时动态管理

ApiSource source = new ApiSource();
source.setDocUrl("https://api.example.com/v3/api-docs");
source.setApiBaseUrl("https://api.example.com");

// 运行时添加:docUrl 同时作为网关运行键和 Harness 配置 Map 键
engine.addApiServer(source);

String docUrl = source.getDocUrl();
ApiSourceClient client = engine.getApiServer(docUrl);
engine.refreshApiServer(docUrl);
engine.removeApiServer(docUrl);

运行时 API 的键语义如下:

API使用的键
Builder.apiServerAdd(name, source)name 写入 Harness 配置 Map;网关仍以 source.docUrl 注册
engine.addApiServer(source)source.docUrl 同时写入配置 Map 和网关
engine.getApiServer(docUrl)网关运行时 docUrl
engine.refreshApiServer(docUrl)网关运行时 docUrl
engine.removeApiServer(docUrl)docUrl 移除网关项,并尝试移除同键配置项
engine.getApiServers()返回 Harness 配置 Map<String, ApiSource>

这意味着 engine.getApiServers() 的 Map 键取决于注册入口:

  • 构建期 .apiServerAdd("orders", source) 的键是 orders
  • 运行时 engine.addApiServer(source) 的键是 source.getDocUrl()

还要注意:如果构建期配置键 ordersdocUrl 不同,removeApiServer(docUrl) 能移除网关运行项,但配置 Map 中的 orders 项不是同一个键。不要把配置 Map 的 name 与网关运行时 docUrl 混为一谈。

5、查看与刷新接口工具

String docUrl = "https://api.example.com/v3/api-docs";
ApiSourceClient client = engine.getApiServer(docUrl);

client.getTools();           // 文档解析出的全部接口工具
client.getToolsActivated();  // 经允许/禁用列表裁剪后的激活工具

client.setAllowedTools(Arrays.asList("getOrder", "listOrders"));
client.setDisallowedTools(Collections.singletonList("deleteOrder"));
engine.refreshApiServer(docUrl);

ApiSourceClient 的运行时过滤配置与网关全局工具索引是两个层次;调整允许/禁用列表后调用 refreshApiServer(docUrl),才能把变化同步到后续 Agent 工具选择中。

6、说明

  • OpenAPI 私域工具权限使用 ToolName.TOOL_OPENAPI,实际工具名为 openapi
  • apiServerAdd(name, source)name 是构建期配置键;运行时管理 API 一律使用 docUrl
  • OpenAPI 工具由 OpenApiGatewayTalent 管理,重试次数由 apiRetries 控制,默认 3。
  • MCP 接入见 《harness - MCP 服务接入》,LSP 接入见 《harness - LSP 服务接入》