OpenRouter 平台功能

OpenRouter 平台功能

路由器元数据

4 分钟阅读

路由器元数据

通过单个选择加入的请求头,在每次响应中呈现路由决策

OpenRouter 的路由器会把每次请求送入多阶段流水线:选择模型服务提供商、可能压缩上下文、可能运行护栏、可能调用服务端工具,并可能对回退目标重试。默认情况下,这些过程都不会出现在响应中。

路由器元数据是一种 按请求选择加入 的功能,会在成功响应中添加 openrouter_metadata 字段,精确记录路由器做了什么。它适用于调试路由决策、归因延迟或成本,以及审计流水线行为。

启用路由器元数据

通过发送值为 enabledX-OpenRouter-Metadata 请求头来选择加入:

curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer <OPENROUTER_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "X-OpenRouter-Metadata: enabled" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [{ "role": "user", "content": "你好" }]
  }'

可接受的值

该请求头接受以下值,匹配时不区分大小写:

行为
enabled在响应中呈现 openrouter_metadata
disabled不呈现元数据。等价于省略该请求头。

任何其他值(包括拼写错误、空字符串和未知级别)都会回退到 disabled。省略该请求头时的默认行为是 disabled

支持的端点

路由器元数据已接入每条公开的补全路由:

  • /api/v1/chat/completions(OpenAI Chat Completions)
  • /api/v1/messages(Anthropic Messages)
  • /api/v1/responses(OpenAI Responses)
  • /api/v1/completions(旧版文本补全)

选择加入后,流式非流式请求都会携带该字段。对于流式响应,openrouter_metadata 会在 data: [DONE] 之前的 最后一个分片 上送达(Chat Completions / Responses),或作为终端 message_stop 事件的一部分送达(Anthropic Messages)。

响应结构

选择加入后,成功响应会在其余响应载荷旁包含 openrouter_metadata 对象:

{
  "id": "gen-...",
  "model": "openai/gpt-4o-mini",
  "choices": [...],
  "usage": {...},
  "openrouter_metadata": {
    "requested": "openai/gpt-4o-mini",
    "strategy": "direct",
    "region": "iad",
    "summary": "available=1, selected=OpenAI",
    "attempt": 1,
    "is_byok": false,
    "endpoints": {
      "total": 1,
      "available": [
        {
          "provider": "OpenAI",
          "model": "openai/gpt-4o-mini",
          "selected": true
        }
      ]
    },
    "attempts": [
      { "provider": "OpenAI", "model": "openai/gpt-4o-mini", "status": 200 }
    ],
    "pipeline": [
      {
        "type": "context_compression",
        "name": "context-compression",
        "data": {
          "engine": "middle-out",
          "input_type": "messages",
          "original_count": 42,
          "compressed_count": 30
        }
      }
    ]
  }
}

字段参考

字段类型说明
requestedstring客户端发送的模型 slug(或别名)。可能与实际提供服务的模型服务提供商/模型不同。
strategystring使用的路由策略:directautofreelatestaliasfallbackparetobodybuilderfusion
regionstring | null处理该请求的边缘区域(若可用)。
summarystring描述路由决策的人类可读一行摘要(例如候选数量、所选模型服务提供商)。
attemptinteger成功的尝试编号,从 1 开始。大于 1 表示先前尝试失败并发生了回退。
is_byokboolean请求是否使用了自带密钥(BYOK,Bring-Your-Own-Key)的模型服务提供商密钥。
endpointsEndpointsMetadata所考虑的端点候选快照,以及哪一个被选中。
paramsRouterParams可选。影响选择的路由器级参数(例如 quality_floorthroughput_floor)。
attemptsAttempt[]可选。路由器对回退目标重试时,每次尝试的模型服务提供商/模型/状态。
pipelinePipelineStage[]可选。实质改变了请求或响应的插件(压缩、护栏、响应修复、服务端工具等)。

完整 schema 记录在 OpenAPI 规范的 OpenRouterMetadata 下,包括 TypeScript 及其他生成客户端的 SDK 类型定义。

流水线阶段

pipeline 数组记录每一个实质影响请求的插件。插件仅在实际运行时才发出阶段;空操作插件(例如上下文压缩发现输入已符合预算)会被省略。当前的阶段类型包括:

typename它告诉你什么
guardrailcontent-filtermoderationflagged: bool,以及引擎特定的判定(decisionconfidence_levelmatched_entity_types 等)。
pluginweb-searchfile-parser插件特定的遥测(例如 Web 搜索的结果数量、文件解析的页数)。
server_toolsserver-tools模式(native / sdk)以及已调用的工具列表。
response_healingresponse-healing模式(json_schema / json_object)、修复是否改进了响应、长度。
context_compressioncontext-compression使用的引擎、输入类型(messages / prompt)、原始与压缩后的数量。

多个插件可以共享同一个 type。要找到特定护栏(例如内容过滤器),遍历该数组并同时匹配 type === 'guardrail'name === 'content-filter'。所有护栏级插件都会发出 type: 'guardrail',因此你可以一并过滤它们(pipeline.filter(s => s.type === 'guardrail')),而无需枚举各个插件。

该列表会随时间增长。将未知阶段类型视为不透明数据。data 按设计是自由形式记录,以便插件在不升级 schema 的情况下附加插件特定的遥测。

缓存命中

缓存命中从不包含 openrouter_metadata。流式和非流式缓存重放都会去掉该字段,以免客户端把行为绑定到过时的路由数据上。这是有意为之:你在缓存未命中时看到的元数据,可能并不能反映生成该缓存载荷时的路由。

错误响应

选择加入后,错误响应会在错误信封的 顶层 呈现 openrouter_metadata,与成功路径的位置一致(作为 error 的兄弟字段,而不是嵌套在其中)。这适用于全部四条路由(Chat Completions、Messages、Responses 和旧版 Completions),以及流式和非流式请求。同样的选择加入规则适用:发送 X-OpenRouter-Metadata: enabled,失败时就会包含该快照;省略则不会。

没有可用的模型服务提供商(404)

{
  "error": {
    "code": 404,
    "message": "No allowed providers are available for the selected model"
  },
  "openrouter_metadata": {
    "requested": "openai/gpt-4o-mini",
    "strategy": "direct",
    "attempt": 0,
    "endpoints": {
      "total": 1,
      "available": [
        {
          "provider": "OpenAI",
          "model": "openai/gpt-4o-mini",
          "selected": false
        }
      ]
    }
  }
}

护栏阻止(403)

当请求在到达模型服务提供商之前被阻止(例如由通过护栏配置的内容过滤器或提示词注入检测器阻止)时,响应会包含完整的 openrouter_metadata 对象,其中有路由上下文以及显示已运行的每个护栏阶段(包括实施阻止的那个)的 pipeline 数组:

{
  "error": {
    "code": 403,
    "message": "Request blocked: prompt injection patterns detected",
    "metadata": {
      "patterns": ["ignore all previous instructions"]
    }
  },
  "openrouter_metadata": {
    "requested": "openai/gpt-4o",
    "strategy": "direct",
    "region": "iad",
    "summary": "available=1",
    "attempt": 1,
    "is_byok": false,
    "endpoints": {
      "total": 1,
      "available": [
        { "provider": "OpenAI", "model": "openai/gpt-4o", "selected": false }
      ]
    },
    "pipeline": [
      {
        "type": "guardrail",
        "name": "regex_pi_detection",
        "guardrail_id": "grd_abc123",
        "guardrail_scope": "api-key",
        "summary": "Blocked: prompt injection detected (1 pattern matched)",
        "data": {
          "action": "blocked",
          "detected": true,
          "engines": ["regex"],
          "patterns": ["ignore all previous instructions"]
        }
      }
    ]
  }
}

由于护栏阻止发生在模型服务提供商调用完成之前,没有任何端点被标记为 selected,可选的 attempts 数组也不会出现。

需要了解的几点:

  • attempt 反映路由器进行到哪一步。 值为 0 表示请求从未到达模型服务提供商,通常是因为所有候选在提交前就被过滤掉了(例如 provider.only 排除了最后一个端点,或允许的模型服务提供商 / 最高价格过滤器拒绝了全部选项)。值为 ≥ 1 表示每次尝试的模型服务提供商都失败,且回退已耗尽。
  • 失败时没有任何端点被标记为 selected endpoints.available[].selected 标志都不会为 true,因为没有任何端点实际返回了 200。
  • 内部错误屏蔽仍然适用。 状态为 500 的响应会被清理为通用消息,并且这些信封按设计会省略 openrouter_metadata。对于原因本已被隐藏的错误,我们不会呈现内部路由细节。其他 5xx 类别(502503504529)在客户端选择加入时仍会包含该元数据。
  • 某些失败模式不会携带它。 身份验证 / 速率限制失败,以及其他在路由器拥有可用路由状态之前就触发的错误(例如 API 边缘的校验拒绝)不会包含该字段。如果你需要某次已越过 API 边缘、但在路由器物化状态之前完成的请求的事后路由上下文,请使用 X-Generation-Id 响应头,通过 GET /api/v1/generation 获取生成记录。

稳定性

openrouter_metadata 的响应结构是可附加的。新的可选字段和流水线阶段类型可能在没有弃用周期的情况下出现,但现有字段是稳定的。请宽松解码(忽略未知字段和阶段类型),你的集成即可向前兼容。

旧版请求头

仍接受旧的请求头名称 X-OpenRouter-Experimental-Metadata,以保持向后兼容。建议在方便时迁移到 X-OpenRouter-Metadata