Skip to content

Agent Providers(OpenAPI Provider) ​

状态:Current —— providers.yaml 是 Agent 侧把外部 HTTP API 接入 Croupier 的一等配置;本文是其完整参考。

Agent 的 providers.yaml(位于 Agent 配置目录,可用 CROUPIER_CONFIG_DIR 指定)把第三方 HTTP API 声明为 openapi provider:Agent 启动时拉取 OpenAPI 文档,把每个 operation 注册为平台函数,控制台目录/调用/OpenAPI Source 绑定均按普通函数使用,无需游戏方编写任何 Croupier 专有代码。

text
providers.yaml ──► Agent openapi provider ──► 拉取 openapiSpec
                       │
                       ▼
        注册函数 <provider>.<operationId>(service: provider:<provider>)
                       │
                       ▼
     调用链:控制台/页面 ─► Server ─► Agent ─► baseUrl(真实 HTTP API)

配置结构 ​

yaml
providers:
  players: # provider 名;函数 ID 前缀(players.player.list)
    enabled: true
    type: openapi # 目前唯一支持的类型
    game_id: default # 归属游戏(与请求 scope 一致才可调用)
    env: dev # 归属环境
    metadata: # 可选;用户自报实例元数据(多 KV,随注册上报 sdk-distribution 页)
      serverId: players-svc-1
    config:
      baseUrl: "http://127.0.0.1:8091" # 上游 API 根地址
      openapiSpec: "http://127.0.0.1:8091/openapi.json" # OpenAPI 3.0 文档 URL
      version: "1.2.0" # 可选;本 provider 契约版本(semver),缺省回退见「函数注册规则」
      timeout: "5s" # 可选;默认 30s("500ms"/"1m" 均可)
      headers: # 可选;全部请求附带的默认 header
        X-Request-Source: croupier
      auth: # 可选;鉴权见下表
        type: bearer
        token: ${PLAYERS_API_TOKEN}

字段参考 ​

字段必填说明
providers.<name>.enabled是false 时跳过加载
providers.<name>.type是仅支持 openapi
providers.<name>.game_id是归属游戏 ID;必须与所属 Agent 注册 scope 一致,为空即报 provider_scope_mismatch(不回退继承 Agent scope)
providers.<name>.env是归属环境(prod/stage/test/dev…);为空同上
providers.<name>.metadata否用户自报实例元数据(serverId 等多 KV);随注册上报,SDK 版本分布页展示/过滤。保留键(gameId/env/sdkLanguage/sdkVersion/sdkName 等)由 Agent 剥离并写注册告警
config.baseUrl是上游 API 根地址,路径直接拼接
config.openapiSpec与 openapiSpecs 二选一OpenAPI 文档 URL
config.openapiSpecs与 openapiSpec 二选一多文档 URL 列表(合并注册)
config.version否本 provider 函数的契约版本(须为合法 semver)
config.timeout否上游调用超时,Go duration 字符串,默认 30s
config.headers否全部请求附带的默认 header
config.auth否鉴权配置,见下

鉴权(config.auth) ​

type字段行为
none(默认)—不附加鉴权
bearertokenAuthorization: Bearer <token>
basicusername / passwordHTTP Basic
api_keyapi_key.name / api_key.value / api_key.in(header 或 query)按位置附加 API key
customcustom_headers附加任意自定义 header 集合

配置值支持 ${ENV_VAR} 环境变量展开(如上例 token),secret 不必写死在文件里。

函数注册规则 ​

  • 函数 ID:<provider名>.<operationId>,例如 provider players + operationId: player.list → players.player.list。operationId 必须稳定——改名等于换函数。

  • 契约来源:summary / description / tags / x-* 治理字段来自 OpenAPI 文档;inputSchema 自动推导——parameters(path/query/header/cookie,调用期均从调用方 payload 取值)逐个成为顶层属性,application/json requestBody 为 object 时其 properties/required 合并进顶层,其他形状归入 body 属性。已知边界:仅解析本地 $ref(#/components/...,循环引用按深度 16 截断为空对象,悬空引用退化为空 schema,非本地引用原样保留);outputSchema 当前不推导(注册为空,页面详情列依赖函数实际返回)。

  • capability 推导(method + path 形状,高置信度):

    形状capability
    GET /{resource}collection_query
    GET /{resource}/{id}item_query
    POST /{resource}create
    PUT/PATCH /{resource}/{id}update
    DELETE /{resource}/{id}delete
    其他(如 POST /{resource}/{id}/kick)action(低置信度)

    可用 x-capability / x-resource / x-operation 显式覆盖;x-execution: task 声明异步任务执行;x-risk / x-permission 声明治理字段;x-approval: required 声明审批要求。

  • 契约版本:解析优先级为 operation 级 x-version > config.version > 文档 info.version > 默认 1.0.0。每一级都要求合法 semver,非法值告警并回退下一级而非丢弃函数——服务端注册门槛(invalid_version)会直接丢弃非 semver 的函数,而 OpenAPI 规范允许 info.version 为任意字符串(如 2026-09),provider 侧在注册前完成归一。

  • 分页:collection 接口的请求带 page/page_size 参数、响应为 {items, total} 形状时,生成的资源页自动带分页绑定。

  • 注册时机:Agent 启动加载 providers.yaml;通过扩展安装下发的 provider 走同一注册路径(SyncExtensionProviders),与静态文件同名冲突时默认静态优先(CROUPIER_EXTENSION_PROVIDER_OVERRIDE_STATIC=1 可反转)。CROUPIER_EXTENSION_PROVIDERS_ONLY=1 时跳过静态文件。

与 OpenAPI Source 的关系 ​

Agent provider 注册的是运行时函数;Dashboard 的「OpenAPI Source」导入的是契约候选。两者通过函数 ID 关联:Source 绑定 kind: provider、functionId: players.player.list 后,契约物化为 FunctionContract(source=openapi)并可生成页面 Proposal。详见 OpenAPI 函数注册。

Dashboard「OpenAPI Sources」页的运行时导入区块读取当前 scope 下的 provider 会话,其数据来自:

http
GET /api/v1/openapi/runtime-sources   # 认证 + X-Game-ID/X-Env scope

每条记录除来源 Agent、函数清单、注册版本与最近心跳外,还带注册链观测字段(#27):

  • metadata:provider 实例自报的用户元数据(serverId=s1 等 key=value 对,仅展示/搜索用);
  • serviceAddr:被调用方(provider 进程)监听地址;
  • firstSeenUnix:导入时间——本进程内首次观测到该 provider 的时刻(服务端归一:无观测值时取 lastSeenUnix);
  • latestVersion:本进程内观测到的最高注册版本,走高不回退(服务端归一:无可解析历史时取 version;与 version 不同说明该 provider 曾以更高版本运行过,页面高亮提示排查)。

边界:firstSeenUnix/latestVersion 为内存态,随会话过期、断连或 server 重启丢失并重新累计,只保证「本进程窗口内」语义(与 lastSeenUnix 的既有先例一致)。

绑定弹窗的函数候选同样包含这些运行时函数(标注导入 Agent)。

本地验证 ​

仓库自带可运行的端到端示例:

bash
go run ./examples/openapi-provider -server 127.0.0.1:19090 -http 127.0.0.1:8091

启动后控制台函数目录(default/dev)应出现 players.player.list 等 6 个函数。示例说明见仓库 examples/openapi-provider/README.md。

自托管部署(docker-compose.deploy.yml)默认随 sdk-examples profile 常驻该示例的容器版(镜像 croupier-openapi-provider-demo,上游走 haproxy:19090,scope 由 CROUPIER_SDK_EXAMPLE_GAME_ID/ENV 注入)——Dashboard「OpenAPI Sources」页的运行时导入区块开箱即有数据,无需手工拉起。

边界 ​

  • OpenAPI 文档只描述 API 契约与能力语义;页面 schema、菜单、多语言、按钮位置等 UI 信息一律不允许进入,导入器遇到会报 diagnostics(见 OpenAPI 输入边界)。
  • 文档支持外部 URL 拉取(provider 场景);Dashboard OpenAPI Source 上传则必须内联(≤2MiB,拒绝外部 $ref)——两条路径的边界不同,注意区分。
  • 自动推导的 inputSchema 是调用方视角的合成 schema(parameters + requestBody 合并),与 API 实际 body 结构未必一一对应:无 requestBody 的操作得到空 object schema;调用期仍按既有 ParameterMapping/RequestBodyMapping 组装请求,schema 只驱动表单与契约展示。
  • 注册链语义相等跳写照常生效:升级 Agent 后已注册函数的 inputSchema 从空变为有值属内容变更,会正常落新契约版本;仪表盘已发布页面需重新生成/发布才会获得真表单。