首页
/ ruflo OpenAPI 文档工程实战:从 Agent 写作规范到 Cognitum v1 契约落地

ruflo OpenAPI 文档工程实战:从 Agent 写作规范到 Cognitum v1 契约落地

2026-09-06 18:59:04作者:裴锟轩Denise

ruflo 仓库内嵌了一套「OpenAPI 文档专家」Agent 定义(.claude/agents/documentation/api-docs/docs-api-openapi.md),用规范化的方式指导如何编写 OpenAPI 3.0/3.1 契约文档。本文以该文档为骨架,结合仓库中真实存在的 Cognitum v1 OpenAPI 规范openapi: 3.1.0)与其背后的 ADR-308 公共 API 契约决策,系统讲解 OpenAPI 文档的结构、最佳实践、契约式治理流程以及「文档与现实漂移」这一真实工程陷阱,帮助你在 ruflo 生态内外写出可被 CI、Agent、LLM 直接消费的高质量 API 文档。

一、这是什么样的文档?一套面向「API 文档写作」的 Agent 人格

仓库中该文件本质是一个 Claude Code Agent 定义:其 frontmatter 声明了 name: api-docsdescription: Expert agent for creating and maintaining OpenAPI/Swagger documentation,正文则是一份完整的角色设定(system prompt)。也就是说,ruflo 并不是把 OpenAPI 写作当作一次性人工任务,而是把它封装成一个可复用的专门 Agent,在与网络打交道的边界上(auth、事件、代理、额度等)持续产出、校验并维护契约文档。

该 Agent 的能力定位(Key responsibilities)可归纳为五个方面:

  1. 编写符合 OpenAPI 3.0 的规范(specification)文件;
  2. 为所有端点撰写 description 与示例;
  3. 精确建模请求/响应 schema;
  4. 完整纳入认证与安全方案(security schemes);
  5. 为所有操作提供清晰可复用的例子。

这套职责在 ruflo 仓库中的真实载体,就是 Cognitum v1 规范:它把 ruflo CLI 与 api.cognitum.one 服务之间的 8 个端点(auth 设备流、令牌交换/吊销、事件上报、事件删除、funnel 策略、代理聊天补全、额度查询)全部写成结构化 YAML。因此,理解「怎么写 OpenAPI 文档」的最佳方式,就是对照这份真实 spec 逐项验证 Agent 的每一条要求。

二、OpenAPI 规范的标准骨架(原文 YAML 全解析)

原文档给出了一份可作为起点的 OpenAPI 3.0 YAML 模板,这是任何 OpenAPI 文档写作的「最小骨架」,此处逐段还原并注明其用途:

openapi: 3.0.0              # 版本声明:3.0.x 或 3.1.x 均须显式写出
info:
  title: API Title           # 必填:API 名称
  version: 1.0.0             # 必填:契约版本,配合语义化版本管理
  description: API Description
servers:
  - url: https://api.example.com   # 服务器地址;多环境可列出多条
paths:
  /endpoint:
    get:
      summary: Brief description     # 短摘要:出现在索引/目录中
      description: Detailed description
      parameters: []                 # 查询/路径/头参数逐一在此声明
      responses:
        '200':
          description: Success response
          content:
            application/json:
              schema:
                type: object
              example:               # 为文档读者提供可直接粘贴的样例
                key: value
components:
  schemas:
    Model:                           # 可复用模型(配合 $ref 引用)
      type: object
      properties:
        id:
          type: string

对照仓库真实 spec,上述骨架在 cognitum-v1.openapi.yaml 中每一块都有更严谨的升级用法:

  • 版本更高但同样显式声明:该文件首行即为 openapi: 3.1.0,紧随其后是一段规范性注释——本 spec 同时 check-in 于 ruflo 与 Cognitum server 两个仓库,双端 CI 都会对照它校验,发生漂移即构建失败。这直接体现「文档是评审产物与单点契约」的价值。
  • servers + security 全局声明servers: [{url: https://api.cognitum.one}],且顶层 security: [{bearerAuth: []}],而无需鉴权的端点(如 /v1/auth/device/v1/funnel-policy)通过端点级 security: [] 显式放行。这种「全局默认鉴权 + 局部显式豁免」是最不容易漏配安全要求的写法。
  • components 的三种复用schemas(如 ApiErrorBodyPolicyVersionsRequestReceiptFunnelEvent)、responsesApiErrorRateLimited)、securitySchemesbearerAuth)。所有端点统一通过 $ref: '#/components/responses/...' 引用错误响应,避免同一个 429/401 形态在多处重复定义、日后改漏。

三、五大写作职责如何落到真实端点:以 Cognitum v1 为镜

原文档要求「为所有端点撰写描述与示例」「精确建模 schema」「包含认证与安全方案」。以下逐条给出仓库中的实证写法,作为可对照的标杆。

3.1 精确建模请求/响应 schema

POST /v1/auth/device(启动 RFC 8628 设备授权流)为例,spec 用 required 数组约束请求与响应的最小契约:

requestBody:
  required: true
  content:
    application/json:
      schema:
        type: object
        required: [client_id, scope]
        properties:
          client_id: { type: string }
          scope:
            type: string
            description: >
              Space-separated scopes ... (account.create, proxy.use,
              cloud.route, telemetry.write, hosted.memory.use)

响应侧则声明必填字段 [device_code, user_code, verification_uri, expires_in, interval],并给出 verification_uriformat: uridescription 里还交代了 scope 与 ADR-302 同意域一一映射的业务语义——这符合原文档「用描述性 summary 与 description」的要求。

令牌端点 POST /v1/auth/token 更进一步演示了 enum 约束数值边界约束

grant_type:
  type: string
  enum: [urn:ietf:params:oauth:grant-type:device_code, authorization_code, refresh_token]
code_verifier: { type: string, description: PKCE verifier }
# 响应中 access token 生命周期被约束为 10–15 分钟:
expires_in: { type: integer, minimum: 600, maximum: 900 }

这类 minimum/maximum/enum/pattern 约束正是「文档与实现强契约」的体现:阅读者无须翻源码即可得知令牌有效期区间与合法授权类型。

3.2 完整记录所有错误响应与速率限制

原文档明确要求「document all possible error responses」「Include rate limiting information」。仓库 spec 通过 components.responses 集中定义了统一的错误响应形态 ApiError(指向 ApiErrorBody)与 RateLimited,后者带三个响应头:

RateLimited:
  description: Rate limited  limits documented per endpoint and echoed in headers
  headers:
    Retry-After: { schema: { type: integer } }
    X-RateLimit-Limit: { schema: { type: integer } }
    X-RateLimit-Remaining: { schema: { type: integer } }

值得注意的错误建模细节(对写作极具参考价值)是 ADR-303 的错误分类法如何在 spec 中落地:

  • 所有错误使用机器可读 code,客户端只按 code 分类、永不解析 message 文案;ApiErrorBody 中 code 的 enum 即为规范全集:cognitum_credit_exhaustedinsufficient_quotarate_limit_exceededauthentication_errorpermission_errorservice_unavailableinvalid_request
  • message 仅供人类阅读,另附 retryable: { type: boolean } 供客户端决定是否重试;
  • 唯一产生 402 的端点被显式注释为「the ONLY source of COGNITUM_CREDIT_EXHAUSTED」,避免多端点语义冲突。

3.3 认证与安全方案的声明

原文档要求「include authentication and security schemes」。仓库 spec 的写法是:

securitySchemes:
  bearerAuth:
    type: http
    scheme: bearer

配合前文提到的顶层 security 与端点级 security: [] 豁免。与之对应的真实 OAuth 客户端实现位于 v3/@claude-flow/security/src/oauth/client.ts,其文件头注释即说明 URL 构造与 POST /oauth/tokenauthorization_code / refresh_token 授权的对应关系,并明确引用这份 check-in 的 OpenAPI spec 作为契约来源——文档声明与安全代码由此形成闭环。

3.4 幂等键与可重试语义写入契约

仓库 spec 在 POST /v1/events 上要求客户端生成的 Idempotency-Keyformat: uuid,每个批次一个,重试不会重复计数),在 POST /v1/events/{subject_id} 的 DELETE 上同时声明 200(已完成,返回 receipt_id + deleted)与 202(服务降级时先收据、服务端重试直至确认)。这类面向故障的契约文档比简单列出「成功/失败」两种响应更能指导真实客户端实现。

四、文档工程的更高形态:把 OpenAPI spec 变成组织级契约(ADR-308)

单一文档如何升级为「跨组织边界的强制契约」?ruflo 的答案是 ADR-308-cognitum-public-api-contract.md。它对「OpenAPI 文档化」提出了六条工程化要求,每一条都可直接复用到其他 API 项目:

  1. 双仓库 check-in + CI 校验:规范同时存在于 ruflo 与 server 仓库,双方 CI 都对照同一 spec 校验,漂移即构建失败。文档因此成为评审任何服务端改动的首要 artifact。
  2. 语义化版本/v1 稳定;破坏性变更必须升 /v2 并提供重叠窗口;CLI 显式声明自己支持的 API 版本。
  3. 幂等键强制POST /v1/events 必须携带客户端生成 UUID,杜绝重试导致的事件/转化重复计数。
  4. 显式限流 + 退避:限流说明写在 spec、通过响应头回传,客户端背压(back off)且绝不向限流重试。
  5. 错误分类法:错误 code 与 ADR-303 的 CreditErrorCode/分类表一一对应,客户端一律按 code 分类。
  6. 数据保留与策略版本收据:契约中直接写明保留策略(原始事件 ≤ 90 天,此后仅聚合数据)、terms/privacy 版本回传与再同意规则。

此外,ADR-308 还定义了客户端侧的规范性故障策略表,这属于 spec 之外但对文档化 API 至关重要的补充约定:

不可用组件 客户端行为
认证(Auth) 本地 ruflo 继续完整工作;受限能力以明确错误降级
遥测(/v1/events 丢弃或使用有界本地队列(≤ 24h、≤ 1MB);绝不阻塞或拖慢 CLI
Funnel 策略 沿用最近一次有效签名策略,否则用包内默认;绝不 fail-open 展示促销
代理后端 向调用方返回错误;绝不静默改路由到其他付费/云厂商
删除 向用户返回持久请求收据,服务端重试直至确认

与之配套的还有同类 ADR 相互引用:错误分类见 ADR-303、funnel 与删除/保留见 ADR-305ADR-309、认证流程见 ADR-306、代理运行时分发见 ADR-304ADR-307。这些 ADR 与 OpenAPI spec 相互印证——一份好的 API 文档从来不是孤立的 YAML,而是与架构决策记录共同演进的。

五、深入 spec 内部:funnel 事件与代理路由 schema 的边界约束艺术

规范写作的价值在封闭枚举与严格 schema 上体现得最充分,仓库 spec 的 components.schemas.FunnelEvent 是绝佳范例:

FunnelEvent:
  type: object
  description: Closed ADR-309 schema  extending the event enum requires an ADR amendment.
  required: [schemaVersion, event, surface, release, timestampBucket]
  additionalProperties: false     # 拒绝未知字段
  properties:
    schemaVersion: { type: integer, const: 1 }     # const 锁定版本
    event:
      type: string
      enum: [disclosure_shown, funnel_disabled, signup_opened, account_created, proxy_activated]
    surface:
      type: string
      enum: [statusline, init, credit_exhaustion]
    release: { type: string }
    region: { type: string, description: Coarse, self-declared only }
    pseudonymousId: { type: string, format: uuid }
    timestampBucket:
      type: string
      pattern: '^\d{4}-\d{2}-\d{2}(T\d{2})?$'      # 仅允许日/小时桶
      description: Daily (default) or hourly bucket  full timestamps are rejected.

这条 schema 传达了多个文档写作要点:const: 1 锁定 schema 版本;additionalProperties: false 让解析器拒绝一切未知字段;用 enum 表达「扩展事件枚举需要走 ADR 修订」的治理约束;用 pattern 从格式层禁止完整时间戳的写入(隐私设计落到 schema 而非口头约定)。

代理路由端点 POST /v1/proxy/chat/completions 则演示了「开放 + 受控」的混合建模:请求侧要求 [model, messages],其中 model 是「具体模型或路由别名 cognitum-auto|low|mid|high」,同时放开 additionalProperties: true 以保持 OpenAI 兼容的透传能力;响应侧除透传内容外,强制内联 RequestReceipt

RequestReceipt:
  type: object
  required: [cost_usd, tier, model, data_plane]
  properties:
    cost_usd: { type: number }
    tier: { type: string }
    model: { type: string }
    data_plane:
      type: string
      description: '"local" or "cloud:<provider>" — visible per request (ADR-304)'

即每次补全都在带内(in-band)返回计量成本、解析后的 tier/model 与数据面,把「谁在处理、花了多少钱」写进契约,而不是依赖客户端事后猜测。

六、诚实记录漂移:一份 OpenAPI 文档的自我约束与局限

对文档作者最有借鉴意义的一点,也许藏在 ADR-308 的 Addendum(2026-07-16)里:实现 ADR-306 时对照线上 OAuth 客户端(cognitum-one/meta-proxyoauth/client.rs,已跑通生产集成测试)发现,实际身份服务走的是 auth.cognitum.one/oauth/{authorize,token}auth.cognitum.one/v1/oauth/code-exchange——与 spec 中 api.cognitum.one/v1/auth/{device,token,revoke} 的 host 和路径方案都不一致

该 ADR 的处理方式极具示范意义:它没有静默放任,而是明确标注——本仓库 check-in 的 spec 对 auth 端点而言是「aspirational(理想的)」而非「authoritative(权威的)」,并解释 ruflo auth 之所以按已被验证的 auth.cognitum.one 面实现,正是为了避免为「没人确认存在的端点」写客户端。仓库 v3/@claude-flow/security/src/oauth/client.ts 的实际实现同样走 /oauth/token/v1/oauth/code-exchange,与这份标注相互佐证。

这提醒每一位 OpenAPI 文档写作者:文档与实现之间的漂移是常态而非异常。规范的写作纪律至少包括——把契约 check-in 到源码库并接入 CI 比对;遇到漂移时在文档/ADR 中显式标记「哪个部分是权威的、哪个部分是理想的」;端到端接入已跑通生产流量的客户端实现后再将文档视为事实来源。

七、如何在 ruflo 中复用以该 Agent 为首的文档工作流

若要在 ruflo 仓库内(或借鉴其模式在其他项目)开展 OpenAPI 文档工作,入口与资产如下:

  1. 阅读并复用 Agent 定义.claude/agents/documentation/api-docs/docs-api-openapi.md 的 frontmatter 已声明其适用描述;后续 Agent 任务可基于该人格调用,产出结构与最佳实践一致的 OpenAPI 文件。
  2. 参考真实标杆v3/docs/api/cognitum-v1.openapi.yaml 是仓库内已落地、且被 CI 与客户端代码共同引用的 3.1 spec(共 8 个端点、343 行),适合作为「精确 schema、统一错误响应、$ref 复用、安全方案声明」的对照蓝本。
  3. 理解契约治理前提:读 ADR-308 了解双仓库 check-in、CI 漂移失败、/v2 语义化版本与规范性故障策略,再结合 ADR-303 的错误 code 全集理解错误建模。
  4. 以源码反哺文档准确性:auth 相关契约以 v3/@claude-flow/security/src/oauth/client.ts 的真实端点为准,谨记 Addendum 的漂移警告——写作前先确认文档描述的端点是否真实存在。

结语

.claude 目录里一份 63 行的 Agent 角色设定出发,ruflo 把「写 OpenAPI 文档」这件事做成了覆盖规范结构、错误建模、安全声明、幂等设计、契约治理与漂移审计的完整工程链路。这份 Agent 文档 提供了方法论骨架,Cognitum v1 specADR-308 则证明了其落地形态:一份可被 CI 校验、可被客户端代码引用、可被后续 Agent 检索续写的 OpenAPI 文档,远比一次性的手工写作更有价值

登录后查看全文
热门项目推荐
相关项目推荐