网关 HTTP API
网关在提供本地 CLI 的同时还暴露了 REST 接口。凡是可以通过 zeroclaw config get/set/list/init/migrate 设置的内容,都可经由 HTTP 访问,因此仪表盘、第三方工具和 CLI 都会驱动同一套底层的 Config 变更核心。
本页面提供高层概览。当前文档化 OpenAPI 子集的字段级定义、请求和响应结构,以及“试用”表单,位于运行中网关的 /api/docs。这些架构来自运行时类型,但路由清单是单独构建的,目前尚未涵盖网关注册的每条路由。crates/zeroclaw-gateway/src/lib.rs 中的路由器仍是完整实际接口面的权威来源。
在 issue #6175 下跟踪。
身份验证
此页面描述的配置值读取和变更受现有配对和 bearer 身份验证保护。通过 /api/docs、/api/openapi.json 和配置 OPTIONS 进行的结构发现是公开的。守护进程启动时会打印首次运行配对码;后续已认证调用会在 Authorization 标头中发送派生的 bearer 令牌。/api/docs 上的 Scalar explorer 提供一个 “Authentication” 面板,你可以在发起已认证调用前粘贴令牌。
默认绑定本地。通过网络访问需要在网关处或其前端进行 TLS 终止;无论 TLS 配置如何,单属性端点和 PATCH 端点都不适合在未经身份验证的情况下暴露。
发现表面
两个端点可以回答“我在这里能做什么?“这个问题:
OPTIONS /api/config返回 whole-config 类型的 JSON Schema。每个构建中保持静态;客户端应根据ETag标头进行缓存。其当前的Allow标头仍列出旧版PUT,但路由器并未注册它。OPTIONS /api/config/prop?path=<dotted>返回特定路径的 schema 片段,并带有Allow: GET, PUT, DELETE, OPTIONS。如果该路径在 schema 中不存在,则返回 404。
OPTIONS 返回功能能力。GET /api/config/prop 和 GET /api/config/list 返回用户的当前值。仪表板中的表单在加载时发起一次 OPTIONS 以获取类型和约束,然后通过 GET 填充字段,再通过 PUT/PATCH 写入。兼容性接口 GET /api/config 还会返回整个配置的快照,并对密钥进行掩码处理,从而使较旧的捆绑仪表板页面在面对较新的网关时不会失败。新客户端应优先使用按属性访问的接口,因为它携带字段元数据并对密钥进行显式处理。
CORS 预检请求(即携带 Access-Control-Request-Method 的请求)会获得标准的预检响应,并在返回 schema 主体之前提前结束。
属性级 CRUD
| 方法 | 路径 | 目的 |
|---|---|---|
GET | /api/config | 兼容性全配置快照(已遮盖机密);新客户端应优先使用按属性提供的接口。 |
PATCH | /api/config | 原子化应用 JSON Patch (RFC 6902) 文档。 |
OPTIONS | /api/config | 整个配置的 JSON Schema(功能能力,而非具体值)。 |
GET | /api/config/prop?path=... | 读取单个字段。密钥仅返回 {path, populated}。 |
PUT | /api/config/prop | 写入一个字段。请求体:{path, value, comment?}。密钥仅返回 {path, populated: true}。 |
DELETE | /api/config/prop?path=... | 将单个字段重置为默认值。机密信息会返回 {path, populated: false}。 |
OPTIONS | /api/config/prop?path=... | 每个字段的架构片段。 |
GET | /api/config/list?prefix=... | 枚举每个可达路径及其类型和类别。密钥条目包含 {path, populated, is_secret: true},但不含值。 |
POST | /api/config/init?section=... | 使用默认值实例化 None 嵌套节。动态映射别名不在此处创建;请使用 POST /api/config/map-key。 |
POST | /api/config/migrate | 就地应用磁盘上的架构迁移。等同于 zeroclaw config migrate。 |
原子批量写入:JSON Patch
PATCH /api/config 接受 JSON Patch 文档(RFC 6902)。支持的配置操作包括 add、replace、remove 和 test。ZeroClaw 还接受用于配置注释的 comment 扩展。配置操作在内存副本上执行;所有操作均应用完毕后,Config::validate() 对结果运行一次。若验证通过,新状态将被持久化并切换生效。若任何操作或最终验证失败,磁盘和内存中的状态均保持不变。注释标注在保存完成后以尽力而为的非致命方式应用。
move 和 copy 返回 400 op_not_supported,因为安全的引用图重写不属于此接口范畴。针对 #[secret] 路径的 test 操作会被拒绝并返回 secret_test_forbidden:差异化的结果将是客户端唯一能读取到的信号,而这会泄露该值。
路径语法:JSON 指针(/agents/researcher/model_provider)或点分形式(agents.researcher.model_provider)。两者均可接受;服务器会进行规范化处理。
命令行对应命令为 zeroclaw config patch <file-or-stdin>,它会对本地 Config 应用相同的操作集,并返回相同结构的响应格式(脚本可使用 --json)。
机密信息:通过 HTTP 进行只写操作
按属性读取绝不会暴露 secret 字段(即 schema 中标记为 #[secret] 或 #[derived_from_secret] 的字段)。它们的响应仅携带 {populated: bool},不包含值、长度、掩码替身或哈希。而兼容性接口 GET /api/config 会在应用 MaskSecrets 后序列化整个配置,因此 secret 字段在此只能以掩码占位符的形式出现。这两种配置读取面都不会返回底层的 secret 值。
PUT 和 PATCH 写入新的密钥值并返回 {populated: true};DELETE 清除该值并返回 {populated: false}。没有任何 HTTP 路径可以通过任何方式检索密钥。
稳定错误代码
错误以 JSON 格式返回,包含一个稳定的 code 字段以及一条便于阅读的 message。前端和脚本根据 code 进行匹配;UI 则根据路径进行匹配。
| 代码 | 状态 | 含义 |
|---|---|---|
path_not_found | 404 | 请求的属性在架构中不存在。 |
validation_failed | 400 | 整个配置的验证器拒绝了建议的状态。 |
dangling_reference | 400 | 配置的别名引用(例如 agents.<x>.model_provider)指向了一个不存在的目标(例如 providers.models.<type>.<alias>)。 |
value_type_mismatch | 400 | 提交的 JSON 值无法强制转换为目标类型。 |
op_not_supported | 400 | JSON Patch 操作为 move / copy / 未知操作。 |
secret_test_forbidden | 400 | JSON Patch test 操作针对了一个机密路径。 |
config_changed_externally | 409 | 磁盘上的配置与内存中的副本发生了偏移。(参见偏移检测。) |
reload_failed | 500 | 保存成功,但守护进程重新加载时无法读取新状态;磁盘上的内容已还原。 |
internal_error | 500 | 服务器端发生未分类的故障。 |
实时探索
网关运行后,可通过 http://<gateway-host>:<port>/api/docs 访问 Scalar API 浏览器。原始规范可在 /api/openapi.json 获取,供其他兼容的查看器使用。
浏览器的身份验证面板会绑定到规范中声明的 bearerAuth 方案,请在发起实时调用之前,将通过配对生成的 bearer 令牌粘贴到此处。该 URL 的 CLI 快捷命令是 zeroclaw config docs。
如果 Scalar 包无法从 CDN 加载(离线/隔离网络环境安装),页面会优雅降级,并将你指向位于 /api/openapi.json 的原始规范,以便你可以使用任何兼容的查看器(Insomnia、Postman、Swagger UI 等)。
事件流契约
GET /api/events 是一个原始的服务器发送事件(Server-Sent Events)流,包含可观测的运行时事件。它不是去重后每轮一行的生命周期时间线。
网关处理器、webhook 处理、cron/heartbeat 任务以及 agent-loop 观察者都可以将符合生命周期形态的事件发布到同一个广播路径中。客户端应将该流视为仅追加的观察日志。如果仪表板需要紧凑的回合时间线,应根据事件载荷中的标识符进行分组或去重,而不是假设每个 agent_start、llm_request 或 agent_end 帧只出现一次。
GET /api/events/history 从同一缓冲区中重放保留的最近事件,按从旧到新的顺序排列。它是为订阅者提供的重连窗口,而非独立的规范生命周期存储。