> ## Documentation Index
> Fetch the complete documentation index at: https://omnirelay.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 标签

> 为调用加上 client=acme、env=prod 这类 key/value 标签，按客户、项目或环境拆分用量与费用。

标签是附在调用上的 key/value 标记，例如 `client=acme` 或 `project=invoices`。OmniRelay 会把标签和请求记录存在一起，控制台就能按客户、项目或环境拆分用量与费用。无需任何配置：给调用加上标签，**用量日志**页面就能看到。

## 为调用添加标签

### 使用 `X-Gateway-Tags` 请求头

以逗号分隔多个 `key=value`，每对前后的空格会被忽略。如果代理重复添加了该请求头，所有副本中的标签都会保留。

```bash theme={null}
curl https://api.omnirelay.ai/v1/chat/completions \
  -H "Authorization: Bearer $OMNIRELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Gateway-Tags: client=acme,env=prod" \
  -d '{"model": "gpt-6-luna", "messages": [{"role": "user", "content": "Hello"}]}'
```

### 使用请求体中的 `tags` 字段

```json theme={null}
{
  "model": "gpt-6-luna",
  "messages": [{"role": "user", "content": "Hello"}],
  "tags": {"client": "acme", "project": "invoices"}
}
```

该字段在请求发往模型服务方之前就会被移除。`tags` 不是对象时（例如部分 SDK 发送的列表）会被忽略，而不是拒绝请求。

### 在 API Key 上设置默认标签

Key 上设置的标签会自动加到用这个 Key 发起的每次调用上。专门服务某个客户或某个环境的 Key，请求里就不必再带标签。在 **API Keys** 页面创建 Key 或打开**密钥设置**时，于**默认标签**一栏填写。

### 通过 OpenAI SDK

```python Python theme={null}
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["OMNIRELAY_API_KEY"],
    base_url="https://api.omnirelay.ai/v1",
    max_retries=0,
    # 此客户端发起的每次调用都会带上
    default_headers={"X-Gateway-Tags": "client=acme,env=prod"},
)

response = client.chat.completions.create(
    model="gpt-6-luna",
    max_completion_tokens=64,
    messages=[{"role": "user", "content": "Hello"}],
    # 只加在本次调用上；同名 key 以此为准
    extra_body={"tags": {"project": "invoices"}},
)
```

```javascript JavaScript theme={null}
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.OMNIRELAY_API_KEY,
  baseURL: "https://api.omnirelay.ai/v1",
  maxRetries: 0,
  defaultHeaders: { "X-Gateway-Tags": "client=acme,env=prod" },
});

const response = await client.chat.completions.create({
  model: "gpt-6-luna",
  max_completion_tokens: 64,
  messages: [{ role: "user", content: "Hello" }],
  // OmniRelay 扩展字段，SDK 会原样放进请求体
  tags: { project: "invoices" },
});
```

## 多个来源的合并

一次调用从多个来源获得标签时，按 key 合并，调用自带的标签优先：请求头覆盖 Key 默认标签，请求体覆盖前两者。

| API Key | 请求头 | 请求体 | 实际记录 |
| - | - | - | - |
| `client=acme,env=dev` | `env=prod` | `{"project": "invoices"}` | `client=acme`、`env=prod`、`project=invoices` |
| `client=acme` | | `{"client": "globex"}` | `client=globex` |
| | `client=acme,env=prod` | `{"client": "globex"}` | `client=globex`、`env=prod` |

## 规则

| | 规则 |
| - | - |
| 数量 | 每次调用最多 10 个，按合并后计算。被调用覆盖的 Key 默认标签只算一次 |
| Key | 1 至 64 个字符，统一存为小写：`Client` 记为 `client` |
| Value | 1 至 128 个字符，按原样保存：`Acme` 与 `acme` 是两个不同的值 |
| 字符 | key 与 value 都只能包含字母、数字和 `-` `_` `.` `:` `/`。不能有空格、逗号、`=` 或带重音的字母 |
| 类型 | value 必须是字符串。请求体里写 `"42"`，不要写 `42` |
| 保留字 | 以 `gateway:` 或 `omnirelay:` 开头的 key |
| 重复 | 同一来源中一个 key 只能出现一次。key 按小写比较，因此同一请求头里的 `Client=a,client=b` 算重复 |

违反规则的调用会返回 `400 invalid_tags`，不会扣费，但仍会作为失败请求出现在**用量日志**中。

> [!WARNING]
>
> 每个不同的值都会在用量拆分中单独占一行。请使用少量稳定的值，例如客户、项目、环境或功能名称。不要把个人信息、请求 ID 或时间戳放进标签。

## 查看带标签的用量

在**用量日志**页面：

* **标签**筛选只保留带有某个标签 key 的调用；填写值后只保留该值。可与模型、模型服务方、Key、状态筛选组合使用。
* **分析 → 分组 → 标签**按某个标签 key 拆分花费、请求数、Token 或错误数。不带该标签的调用单独成一行，各行之和等于总计。
* **请求**日志会显示每次调用的标签，导出的 CSV 也有 `tags` 列。

要查看某一次调用实际记录了哪些标签，请开启[请求元数据](https://omnirelay.ai/docs/cn/llms/request-metadata.md)。

## 兼容性

这些请求头与字段过去带有 OmniRelay 名称。旧名**永久保留**，继续接受并返回，没有下线日期，已上线的集成无需改动：

| 现名 | 旧名 | 行为 |
| - | - | - |
| 请求头 `X-Gateway-Tags` | `X-OmniRelay-Tags` | 两者都读。同时发送且值不同时以新名为准，元数据里会标记 `"deprecated_header": "x-omnirelay-tags"` |
| 请求头 `X-Gateway-Metadata` | `X-OmniRelay-Metadata` | 规则相同 |
| 响应字段 `gateway_metadata` | `omnirelay_metadata` | 两个字段同时返回，内容相同 |
| 响应头 `X-Gateway-Cost-Microusd`（Gemini 风格调用） | `X-OmniRelay-Cost-Microusd` | 两个响应头同时返回，值相同 |
| 保留标签前缀 `gateway:` | `omnirelay:` | 两者都保留 |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.