214 214
215### `upstreams`215### `upstreams`
216 216
217`upstreams` 是一个有序列表。网关将推理转发到解析请求的模型的第一个上游。217`upstreams` 是一个有序列表。网关会将推理请求转发到第一个能解析所请求模型的上游,并跳过任何其 [`groups` 列表](#send-each-team-to-its-own-upstream)不包含该开发者的上游。
218 218
219在 `5xx`、`429`、`401`、`403`、`404` 或超时时,网关故障转移到下一个上游;其他 `4xx` 不会,因为这些错误可归因于请求而不是上游。`401` 或 `403` 意味着上游拒绝了网关使用的凭据,或拒绝其访问,例如对所请求模型的访问。`404` 意味着该上游不提供请求的模型,因此列表中的后续上游仍然可以。219在 `5xx`、`429`、`401`、`403`、`404` 或超时时,网关故障转移到下一个上游;其他 `4xx` 不会,因为这些错误可归因于请求而不是上游。`401` 或 `403` 意味着上游拒绝了网关使用的凭据,或拒绝其访问,例如对所请求模型的访问。`404` 意味着该上游不提供请求的模型,因此列表中的后续上游仍然可以。
220 220
231网关返回一个上游的错误响应或其自己的 `502`,取决于上游如何应答:231网关返回一个上游的错误响应或其自己的 `502`,取决于上游如何应答:
232 232
233* **上游返回网关不[故障转移](#multiple-upstreams)的状态**:该上游的响应。网关不尝试进一步的上游。233* **上游返回网关不[故障转移](#multiple-upstreams)的状态**:该上游的响应。网关不尝试进一步的上游。
234* **网关尝试的每个上游都以网关[故障转移](#multiple-upstreams)的方式失败**:最后一个 `429`。当没有返回 `429` 时,网关按顺序优先选择最后一个 `401` 或 `403`、最后一个 `404` 和最后一个 `501`。当没有返回任何这些时,网关自己的 `502`,`all upstreams failed (N attempted)`,其中 N 计算 [`upstreams`](#upstreams) 中的每个条目,包括网关跳过的条目,因为它们不提供请求的模型。234* **网关尝试的每个上游都以会触发[故障转移](#multiple-upstreams)的方式失败**:返回最后一个 `429`。如果没有任何上游返回 `429`,网关按顺序优先返回最后一个 `401` 或 `403`、最后一个 `404`、最后一个 `501`。如果都没有返回这些状态,则返回网关自身的 `502`,即 `all upstreams failed (N attempted)`。N 统计您的 [`upstreams`](#upstreams) 条目(包括被跳过的条目),减去 [`groups`](#send-each-team-to-its-own-upstream) 列表不包含该开发者的条目。
235 235
236当网关返回上游的响应时,它保持上游的状态代码。它是否保持上游的消息取决于提供商。Anthropic API 上游的错误正文不变地到达开发人员。236当网关返回上游的响应时,它保持上游的状态代码。它是否保持上游的消息取决于提供商。Anthropic API 上游的错误正文不变地到达开发人员。
237 237
289 base_url: https://upstream-gateway.internal.example.com289 base_url: https://upstream-gateway.internal.example.com
290 auth:290 auth:
291 api_key: ${PROXY_KEY}291 api_key: ${PROXY_KEY}
292 forward_user_identity: true # 默认 false292 forward_user_identity: true # default false
293```293```
294 294
295网关将这些标头添加到它转发到该上游的每个请求。295网关将这些标头添加到它转发到该上游的每个请求。
320upstreams:320upstreams:
321 - provider: bedrock321 - provider: bedrock
322 region: us-east-1322 region: us-east-1
323 auth: {} # 首选:AWS 默认凭据链323 auth: {} # preferred: AWS default credential chain
324 # 或显式凭据:324 # OR explicit credentials:
325 # auth:325 # auth:
326 # aws_access_key_id: ${AWS_AKID}326 # aws_access_key_id: ${AWS_AKID}
327 # aws_secret_access_key: ${AWS_SK}327 # aws_secret_access_key: ${AWS_SK}
328 # aws_session_token: ${AWS_ST}328 # aws_session_token: ${AWS_ST}
329 # 或 Bedrock API 持有者令牌:329 # OR a Bedrock API bearer token:
330 # auth:330 # auth:
331 # aws_bearer_token: ${AWS_BEARER_TOKEN}331 # aws_bearer_token: ${AWS_BEARER_TOKEN}
332 # 为 FIPS 或 VPC 端点部署覆盖 bedrock-runtime 端点:332 # Override the bedrock-runtime endpoint for FIPS or VPC-endpoint deployments:
333 # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com333 # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com
334```334```
335 335
356 region: us-east-1356 region: us-east-1
357 auth: {}357 auth: {}
358 guardrail:358 guardrail:
359 id: gr-abc123 # 防护栏 ID 或完整 ARN359 id: gr-abc123 # guardrail ID or full ARN
360 version: "1" # 已发布的版本号或 DRAFT360 version: "1" # a published version number, or DRAFT
361 # 保留引号:裸 1 在启动时失败361 # keep the quotes: a bare 1 fails at boot
362```362```
363 363
364> [!WARNING]
365>
366> 网关不支持防护栏输入标签。它不向提示词添加防护内容标签,因此 Amazon Bedrock 仅应用于标记输入的防护栏过滤器不在通过网关的流量上运行。对于哪些过滤器依赖输入标签,请参阅 Amazon Bedrock 文档中的[输入标签](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-tagging.html)。
367
368也在防护栏上授予 `bedrock:ApplyGuardrail` 给签署此上游请求的主体:网关的 AWS 主体,或使用 [`assume_role`](#bedrock-in-another-aws-account) 的 `role_arn` 中命名的角色。364也在防护栏上授予 `bedrock:ApplyGuardrail` 给签署此上游请求的主体:网关的 AWS 主体,或使用 [`assume_role`](#bedrock-in-another-aws-account) 的 `role_arn` 中命名的角色。
369 365
370在每个 `bedrock` 上游或不在任何上游上设置 `guardrail`。网关拒绝在混合上启动,因为[故障转移](#multiple-upstreams)可能会将请求发送到没有防护栏的 Bedrock 上游。366在每个 `bedrock` 上游或不在任何上游上设置 `guardrail`。网关拒绝在混合上启动,因为[故障转移](#multiple-upstreams)可能会将请求发送到没有防护栏的 Bedrock 上游。
373 369
374当 `/v1/messages` 请求的正文携带 `amazon-bedrock-*` 字段(如 `amazon-bedrock-guardrailConfig`)到达设置了 `guardrail` 的 Bedrock 上游时,网关应答 400 而不是转发它。370当 `/v1/messages` 请求的正文携带 `amazon-bedrock-*` 字段(如 `amazon-bedrock-guardrailConfig`)到达设置了 `guardrail` 的 Bedrock 上游时,网关应答 400 而不是转发它。
375 371
372> [!WARNING]
373>
374> 默认情况下,网关不会向提示词添加输入标签,因此 Amazon Bedrock 仅对带标签输入应用的防护栏过滤器不会在经过网关的流量上运行。要添加标签,请设置 [`input_tagging`](#add-guardrail-input-tags)。有关哪些过滤器依赖于输入标签,请参阅 Amazon Bedrock 文档中的[输入标签](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-tagging.html)。
375
376##### 添加防护栏输入标签
377
378要让网关添加 Amazon Bedrock 防护栏的[提示词攻击过滤器](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-prompt-attack.html)所需的输入标签,请在 `guardrail` 块中设置 `input_tagging` 并重启网关。在每个 `bedrock` 上游上设置相同的值,否则网关会拒绝启动。要求网关服务器上运行 Claude Code v2.1.316 或更高版本。不支持该键的版本的网关会在启动时以 `Unrecognized key(s) in object: 'input_tagging'` 退出。
379
380> [!WARNING]
381>
382> 根据 [Amazon Bedrock 的文档](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-tagging.html),一旦请求携带输入标签,防护栏中的每个过滤器都会停止评估未加标签的内容。在开发者使用的网关上设置 `input_tagging` 之前,请先在测试网关上试用。
383
384`input_tagging` 接受以下值之一:
385
386| `input_tagging` | 网关为哪些文本加标签 | 防护栏拦截提示词之后 |
387| :- | :- | :- |
388| `last_message` | 自 Claude 上次回复以来的 `user` 消息 | 在 Claude Code 中,下一个提示词可以通过,随后 Claude 会将被拦截的提示词作为对话的一部分接收 |
389| `user_messages` | `user` 消息 | 会话中后续的提示词也可能被拦截,直到开发者删除被拦截的提示词 |
390| `all_messages` | `user` 和 `assistant` 消息 | 与 `user_messages` 相同 |
391| `all_messages_and_system` | 系统提示词和每条消息,包括[对话中途的系统消息](https://code.claude.com/docs/zh-CN/llm-gateway-protocol.md#feature-pass-through) | 与 `user_messages` 相同 |
392
393使用 `last_message` 时,如果自 Claude 上次回复以来的 `user` 消息中没有可加标签的文本,网关会改为给自该回复以来的对话中途系统消息加标签。工具调用也算作一次回复。
394
395Amazon Bedrock 对提示词攻击过滤器的指导是[为用户输入加标签以排除系统提示词](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-prompt-attack.html)。如果您设置 `all_messages_and_system`,标记 Claude Code 自身系统提示词的过滤器可能会拦截请求。
396
397以下示例为每条 `user` 消息中的文本加标签:
398
399```yaml theme={null}
400upstreams:
401 - provider: bedrock
402 region: us-east-1
403 auth: {}
404 guardrail:
405 id: gr-abc123
406 version: "1"
407 input_tagging: user_messages
408```
409
410`user` 消息中还可能包含 Claude Code 添加的文本,例如[系统提醒](https://code.claude.com/docs/zh-CN/glossary.md#system-reminder),因此请在测试网关上确认普通请求不会被拦截。
411
412在 Anthropic 的测试中,加了标签的会话在相邻提示词之间保持了[提示缓存](https://code.claude.com/docs/zh-CN/prompt-caching.md)读取,并且标签没有增加输入 token。
413
414##### 输入标签不覆盖的内容
415
416没有任何 `input_tagging` 值能阻止故意将文本放在不加标签位置的开发者。不要指望防护栏评估请求的以下部分:
417
418* **网关不加标签的内容**:您的 `input_tagging` 值未包含的消息、工具定义、工具调用输入、图像和 PDF 等。除非您设置 `all_messages_and_system`,否则系统提示词也不加标签。
419* **工具结果**:这些内容包含 Claude 的工具返回的内容,例如文件内容和网页。在 Anthropic 的测试中,无论是否加标签,字词过滤器都不会评估它们。
420
421如果您的 AWS 账号或组织强制执行防护栏,请参阅 [Amazon Bedrock 的文档](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-enforcements.html),了解该防护栏如何处理输入标签。
422
423##### 记录触发的防护栏过滤器
424
425要找出是哪个 Amazon Bedrock 防护栏过滤器拦截了开发者的请求,请在 Bedrock 上游上设置 `guardrail_trace: true`,重启网关,然后让开发者重新发送该请求。接着在[审计日志](https://code.claude.com/docs/zh-CN/claude-apps-gateway-deploy.md#logs)中找到该请求的 `guardrail.trace` 事件。需要网关服务器上运行 Claude Code v2.1.314 或更高版本。更早版本的网关在发现 `guardrail_trace` 时会拒绝启动。
426
427```yaml theme={null}
428upstreams:
429 - provider: bedrock
430 region: us-east-1
431 auth: {}
432 guardrail:
433 id: gr-abc123
434 version: "1"
435 guardrail_trace: true # default false; beside guardrail, not inside it
436```
437
438当某个过滤器触发或防护栏的操作为 `INTERVENED` 时,网关会写入一个 `guardrail.trace` 事件,其中不包含匹配的文本。可通过 `email` 或 `sub` 查找开发者的事件。一个流式请求可能产生多个事件,其中一个的 `filters` 列表可能为空,因此请阅读具有相同 `request_id` 的所有事件:
439
440| 字段 | 内容 |
441| - | - |
442| `request_id` | 请求的 ID |
443| `sub`、`email` | 开发者的用户 ID 和电子邮件 |
444| `upstream` | 回复来自的上游 |
445| `action` | 防护栏的操作,例如 `INTERVENED` |
446| `filters` | 触发的过滤器。当 AWS 未发送过滤器详情时,列表为空 |
447| `filters[].side` | `input` 或 `output` |
448| `filters[].guardrail` | 防护栏的 ID |
449| `filters[].policy` | Bedrock 策略和列表,例如 `contentPolicy.filters` 或 `sensitiveInformationPolicy.piiEntities` |
450| 其他 `filters[]` 字段 | 条目还可能包含 `action`、`name`、`type`、`confidence`、`filterStrength`、`score` 和 `threshold` 等字段 |
451
452该事件不包含过滤器匹配的文本,包括 Bedrock 跟踪中的 `match` 字段。开发者不会收到 Bedrock 的跟踪数据,因为网关会从每个回复(无论是否流式)中将其删除。
453
454如果客户端在 `/v1/messages` 请求正文中发送 `amazon-bedrock-*` 字段,网关在设置了 `guardrail_trace` 的上游上会返回 400。
455
376##### 另一个 AWS 帐户中的 Bedrock456##### 另一个 AWS 帐户中的 Bedrock
377 457
378在 Bedrock 上游上设置 `assume_role`,网关仅使用其自己的 AWS 身份来调用您命名的角色上的 `sts:AssumeRole`,该角色可以在与网关不同的 AWS 帐户中。该上游的每个 Bedrock 请求都使用 STS 返回的一小时凭据签署,因此没有长期访问密钥跨帐户。458在 Bedrock 上游上设置 `assume_role`,网关仅使用其自己的 AWS 身份来调用您命名的角色上的 `sts:AssumeRole`,该角色可以在与网关不同的 AWS 帐户中。该上游的每个 Bedrock 请求都使用 STS 返回的一小时凭据签署,因此没有长期访问密钥跨帐户。
384 - name: bedrock-isolated464 - name: bedrock-isolated
385 provider: bedrock465 provider: bedrock
386 region: us-east-1466 region: us-east-1
387 auth: {} # 网关自己的角色:它仅调用 STS467 auth: {} # the gateway's own role: it only calls STS
388 assume_role:468 assume_role:
389 role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock469 role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
390 # external_id: ${BEDROCK_ROLE_EXTERNAL_ID} # 当角色的信任策略需要时470 # external_id: ${BEDROCK_ROLE_EXTERNAL_ID} # when the role's trust policy requires one
391```471```
392 472
393`assume_role` 块采用三个键:473`assume_role` 块采用三个键:
415* 如果 STS 拒绝或无法到达,网关不使用上游自己的凭据发送请求。它记录 STS 错误和要检查的内容,然后尝试您列出的下一个上游。[上游错误消息](#upstream-error-messages)覆盖当没有上游成功时客户端接收的内容。没有 `assume_role` 的后续上游将使用其自己的凭据提供请求,因此仅在这是您想要的情况下列出一个。495* 如果 STS 拒绝或无法到达,网关不使用上游自己的凭据发送请求。它记录 STS 错误和要检查的内容,然后尝试您列出的下一个上游。[上游错误消息](#upstream-error-messages)覆盖当没有上游成功时客户端接收的内容。没有 `assume_role` 的后续上游将使用其自己的凭据提供请求,因此仅在这是您想要的情况下列出一个。
416* 网关调用区域 STS 端点 `sts.<region>.amazonaws.com`,其网络必须到达。对于 FIPS 端点,在网关的环境中设置 `AWS_USE_FIPS_ENDPOINT=true` 而不是在 AWS 配置文件中的 `use_fips_endpoint`。496* 网关调用区域 STS 端点 `sts.<region>.amazonaws.com`,其网络必须到达。对于 FIPS 端点,在网关的环境中设置 `AWS_USE_FIPS_ENDPOINT=true` 而不是在 AWS 配置文件中的 `use_fips_endpoint`。
417* `assume_role` 仅适用于 `provider: bedrock` 并需要 SigV4 源凭据:当它在 `aws_bearer_token` 旁边设置时,网关拒绝启动。497* `assume_role` 仅适用于 `provider: bedrock` 并需要 SigV4 源凭据:当它在 `aws_bearer_token` 旁边设置时,网关拒绝启动。
418* 网关允许的每个开发人员都可以使用此上游;[`managed`](#managed) 控制哪些开发人员可能使用哪些模型。要保持通过角色提供的模型也不从另一个帐户提供,给它一个自定义 id,其 `upstream_model` 映射仅具有此上游的名称。对于这样的 id,网关跳过每个其他上游,因此请求和放弃请求的 token 计数都无法故障转移到另一个帐户。对内置模型名称的请求仍可能[到达此上游](#multiple-upstreams),网关会使用同一角色对其签名。除非其帐户也应该提供这些模型,否则请将此上游列在最后。498* 如果没有 [`groups` 列表](#send-each-team-to-its-own-upstream),网关允许的每位开发者都可以使用此上游。要限制开发者可以使用的模型,请在 [`managed`](#managed) 策略中设置 `availableModels`。
499* 要防止通过该角色提供的模型也从其他账号提供,请为其指定一个自定义 id,使其 `upstream_model` 映射仅包含此上游的名称。对于这样的 id,网关会跳过所有其他上游,因此无论是请求本身还是针对被中止请求的 token 计数,都不会故障转移到其他账号。
500* 对内置模型名称的请求仍可能[到达此上游](#multiple-upstreams),网关会使用同一角色对其签名。除非该账号也应提供这些模型,否则请将此上游列在最后。
419 501
420此示例给一个模型一个自定义 id,仅隔离上游提供:502此示例给一个模型一个自定义 id,仅隔离上游提供:
421 503
422```yaml theme={null}504```yaml theme={null}
423models:505models:
424 - id: restricted-claude-opus-4-8 # 自定义 id,不是内置模型名称506 - id: restricted-claude-opus-4-8 # a custom id, not a built-in model name
425 upstream_model:507 upstream_model:
426 bedrock-isolated: us.anthropic.claude-opus-4-8 # 唯一提供它的上游508 bedrock-isolated: us.anthropic.claude-opus-4-8 # the only upstream that serves it
427```509```
428 510
429##### 每开发人员 AWS 成本属性511##### 每开发人员 AWS 成本属性
436upstreams:518upstreams:
437 - provider: bedrock519 - provider: bedrock
438 region: us-east-1520 region: us-east-1
439 auth: {} # 网关自己的角色:它仅调用 STS521 auth: {} # the gateway's own role: it only calls STS
440 assume_role:522 assume_role:
441 role_arn: arn:aws:iam::123456789012:role/claude-gateway-bedrock-user523 role_arn: arn:aws:iam::123456789012:role/claude-gateway-bedrock-user
442 session_name: email # 或 sub524 session_name: email # or sub
443```525```
444 526
445`session_name` 选择哪个已验证的声明成为 AWS `RoleSessionName`:`email` 或 `sub`。网关将除 ASCII 字母、数字和 `_+,.@-` 之外的任何字符写成 `=XX` 十六进制(按 UTF-8 字节),并将长于 64 字符的结果缩短为前缀加哈希,因此每个开发人员的会话名称保持有效且唯一。来自其令牌缺少声明的开发人员的请求不通过此上游发送,操作员日志说切换到 `sub` 或设置 [`oidc.email_claim`](#oidc)。527`session_name` 选择哪个已验证的声明成为 AWS `RoleSessionName`:`email` 或 `sub`。网关将除 ASCII 字母、数字和 `_+,.@-` 之外的任何字符写成 `=XX` 十六进制(按 UTF-8 字节),并将长于 64 字符的结果缩短为前缀加哈希,因此每个开发人员的会话名称保持有效且唯一。来自其令牌缺少声明的开发人员的请求不通过此上游发送,操作员日志说切换到 `sub` 或设置 [`oidc.email_claim`](#oidc)。
460upstreams:542upstreams:
461 - provider: mantle543 - provider: mantle
462 region: us-east-1544 region: us-east-1
463 models: [claude-opus-4-7, claude-haiku-4-5] # 必需545 models: [claude-opus-4-7, claude-haiku-4-5] # required
464 auth: {} # AWS 默认凭据链546 auth: {} # AWS default credential chain
465 - provider: bedrock547 - provider: bedrock
466 region: us-east-1548 region: us-east-1
467 auth: {}549 auth: {}
499 region: us-east-1581 region: us-east-1
500 workspace_id: wrkspc_...582 workspace_id: wrkspc_...
501 auth:583 auth:
502 api_key: ${ANTHROPIC_AWS_API_KEY} # 作为 x-api-key 发送584 api_key: ${ANTHROPIC_AWS_API_KEY} # sent as x-api-key
503 # 或通过 AWS 默认凭据链的 SigV4:585 # OR SigV4 via the AWS default credential chain:
504 # auth: {}586 # auth: {}
505 # 或显式 SigV4 凭据:587 # OR explicit SigV4 credentials:
506 # auth:588 # auth:
507 # aws_access_key_id: ${AWS_ACCESS_KEY_ID}589 # aws_access_key_id: ${AWS_ACCESS_KEY_ID}
508 # aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}590 # aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}
509 # 覆盖派生的端点:591 # Override the derived endpoint:
510 # base_url: https://aws-external-anthropic.us-east-1.api.aws592 # base_url: https://aws-external-anthropic.us-east-1.api.aws
511```593```
512 594
531 - provider: vertex613 - provider: vertex
532 region: us-east5614 region: us-east5
533 project_id: example-prod615 project_id: example-prod
534 auth: {} # 首选:应用默认凭据616 auth: {} # preferred: Application Default Credentials
535 # 或服务帐户密钥文件:617 # OR a service account key file:
536 # auth: { service_account_json: /secrets/sa.json }618 # auth: { service_account_json: /secrets/sa.json }
537 # 为私有服务连接覆盖 aiplatform 端点:619 # Override the aiplatform endpoint for Private Service Connect:
538 # base_url: https://us-east5-aiplatform.p.googleapis.com620 # base_url: https://us-east5-aiplatform.p.googleapis.com
539```621```
540 622
558upstreams:640upstreams:
559 - provider: foundry641 - provider: foundry
560 resource: example-foundry # https://example-foundry.services.ai.azure.com642 resource: example-foundry # https://example-foundry.services.ai.azure.com
561 auth: { use_azure_ad: true } # 首选:DefaultAzureCredential / 托管身份643 auth: { use_azure_ad: true } # preferred: DefaultAzureCredential / Managed Identity
562 # 或 API 密钥:644 # OR an API key:
563 # auth:645 # auth:
564 # api_key: ${FOUNDRY_API_KEY}646 # api_key: ${FOUNDRY_API_KEY}
565```647```
627 709
628`429` 是按上游容量,因此预配吞吐量 (PT) 耗尽故障转移到按需。如果您在上游上设置 [`forward_user_identity: true`](#per-user-identity-headers-for-a-proxy-you-run),对携带开发人员电子邮件的请求的 `429` 是按用户拒绝而不是故障转移。710`429` 是按上游容量,因此预配吞吐量 (PT) 耗尽故障转移到按需。如果您在上游上设置 [`forward_user_identity: true`](#per-user-identity-headers-for-a-proxy-you-run),对携带开发人员电子邮件的请求的 `429` 是按用户拒绝而不是故障转移。
629 711
630每个请求从第一个上游开始。请求仅在它前面的每个上游都失败或不提供请求的模型时才到达后续上游。712仅在以下情况下,请求才会越过某个上游:
713
714* 该上游已失败
715* 该上游不提供所请求的模型
716* 该上游的 [`groups` 列表](#send-each-team-to-its-own-upstream)不包含该开发者
631 717
632网关不保持失败上游的记录,因此当上游关闭时,到达它的每个请求仍然尝试它并等待它失败后再继续。718网关不保持失败上游的记录,因此当上游关闭时,到达它的每个请求仍然尝试它并等待它失败后再继续。
633 719
680| - | - |766| - | - |
681| 不同区域 | 每个区域一个 Amazon Bedrock 上游,每个都有自己的 `region:`。使用 [`auto_include_builtin_models: true`](#models) 跨区域推理配置文件自动路由;对于区域固定部署,使用 `models:` 块。 |767| 不同区域 | 每个区域一个 Amazon Bedrock 上游,每个都有自己的 `region:`。使用 [`auto_include_builtin_models: true`](#models) 跨区域推理配置文件自动路由;对于区域固定部署,使用 `models:` 块。 |
682| 不同帐户 | 每个帐户一个 Amazon Bedrock 上游。默认链 (`auth: {}`) 使用 pod 的身份;对于第二个帐户,添加 [`assume_role`](#bedrock-in-another-aws-account) 以使用短期凭据到达它,或在 `auth:` 中设置显式凭据或持有者令牌。 |768| 不同帐户 | 每个帐户一个 Amazon Bedrock 上游。默认链 (`auth: {}`) 使用 pod 的身份;对于第二个帐户,添加 [`assume_role`](#bedrock-in-another-aws-account) 以使用短期凭据到达它,或在 `auth:` 中设置显式凭据或持有者令牌。 |
769| 不同团队 | 为每个团队的上游提供一个 `groups` 列表,使只有这些 IdP 组中的开发者才能访问它。请参阅[将每个团队发送到各自的上游](#send-each-team-to-its-own-upstream)。 |
683| 预配吞吐量 | 将模型映射到该上游名称的 `models:` 中的预配吞吐量 ARN。其他上游保持按需 ID,因此 PT 容量在故障转移前耗尽。 |770| 预配吞吐量 | 将模型映射到该上游名称的 `models:` 中的预配吞吐量 ARN。其他上游保持按需 ID,因此 PT 容量在故障转移前耗尽。 |
684| VPC / FIPS 端点 | 在上游上设置 `base_url:` 到您的 VPC 端点或 FIPS 端点 URL |771| VPC / FIPS 端点 | 在上游上设置 `base_url:` 到您的 VPC 端点或 FIPS 端点 URL |
685| 模型范围路由 | 仅自定义模型 `id`(即不是内置 Claude 模型的 id)会跳过其 `upstream_model:` 映射中不存在的上游。`mantle` 上游仅针对其 [`models` 字段](#amazon-bedrock-mantle-endpoint)中列出的模型被尝试。在其他每个上游上,网关按顺序尝试内置模型,并在映射没有条目时使用提供商的默认 ID,因此对于内置模型,映射改变上游接收的 ID 而不是它是否被尝试;拒绝 ID 的上游遵循与任何其他上游错误相同的[故障转移规则](#upstreams)。 |772| 按模型路由 | 自定义模型 `id`(即非内置 Claude 模型的 ID)会跳过其 `upstream_model:` 映射中未列出的上游。带有 `models` 列表的上游([`mantle` 上游](#amazon-bedrock-mantle-endpoint)必须有此列表)仅会针对这些模型进行尝试。 |
773| 内置模型路由 | 对于没有 `models` 或 `groups` 列表的上游,网关会按顺序尝试内置模型,并在 `upstream_model:` 映射中没有条目时使用提供商的默认 ID。对于提供商有默认 ID 的内置模型,该映射改变的是上游接收的 ID,而不是是否尝试该上游。拒绝该 ID 的上游遵循与其他任何上游错误相同的[故障转移规则](#upstreams)。 |
686 774
687在云提供商之间或直接 Anthropic API 之间故障转移改变哪个协议、地理位置和其他条款控制请求。775在云提供商之间或直接 Anthropic API 之间故障转移改变哪个协议、地理位置和其他条款控制请求。
688 776
689CLI 对网关应用相同的功能门控,无论哪个上游提供给定请求,因此默认情况下故障转移不会发送上游会拒绝的正文字段。如果您在策略中设置了[一小时缓存 TTL](#one-hour-prompt-cache),它会发送到列表中的每个上游,因此仅当所有上游都接受它时才设置。777CLI 对网关应用相同的功能门控,无论哪个上游提供给定请求,因此默认情况下故障转移不会发送上游会拒绝的正文字段。如果您在策略中设置了[一小时缓存 TTL](#one-hour-prompt-cache),它会发送到列表中的每个上游,因此仅当所有上游都接受它时才设置。
690 778
779#### 将每个团队发送到各自的上游
780
781要将每个团队的请求发送到其各自的 AWS 账户或 Google Cloud 项目,请为每个团队列出一个上游,并为每个上游提供一个 `groups` 列表。只有所列 IdP 组中的开发者才能访问该上游,无论是首次尝试还是[故障转移](#multiple-upstreams)。所有提供商都支持 `groups`。网关服务器上需要 Claude Code v2.1.314 或更高版本。
782
783以下示例为 `payments-eng` 和 `search-eng` 组各分配一个 AWS 账户,并添加一个没有 `groups` 列表、所有开发者都可使用的上游:
784
785```yaml theme={null}
786upstreams:
787 - name: bedrock-payments
788 provider: bedrock
789 region: us-east-1
790 auth: {}
791 assume_role:
792 role_arn: arn:aws:iam::111111111111:role/claude-gateway-bedrock
793 groups: [payments-eng]
794 - name: bedrock-search
795 provider: bedrock
796 region: us-east-1
797 auth: {}
798 assume_role:
799 role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
800 groups: [search-eng]
801 - name: bedrock-shared # no groups: open to everyone, so listed last
802 provider: bedrock
803 region: us-east-1
804 auth: {}
805```
806
807使用该示例配置时,每个开发者的请求从其所在行的第一个上游开始,并在故障转移时移至下一个:
808
809| 开发者所属组 | 上游(按顺序) |
810| - | - |
811| `payments-eng` | `bedrock-payments`,然后 `bedrock-shared` |
812| `search-eng` | `bedrock-search`,然后 `bedrock-shared` |
813| `payments-eng` 和 `search-eng` | `bedrock-payments`,然后 `bedrock-search`,然后 `bedrock-shared` |
814| 均不属于 | `bedrock-shared` |
815
816当团队的上游以 `403` 拒绝所请求的模型时,网关会尝试该团队所在行中提供该模型的下一个上游。要将团队限定在一个上游,请为每个上游提供 `groups` 列表,并确保没有其他上游列出该团队开发者所属的组。这样该团队将没有故障转移,而不属于任何所列组的开发者发出的请求将[以 `400` 失败](#what-happens-when-a-developer-is-in-no-listed-group)。
817
818要让每个开发者到达您预期的上游,请编写完全匹配的条目,并将开放的上游放在最后:
819
820* **条目**:按照您的 IdP 在 [groups 声明](#oidc)中发送的形式准确编写每个组,[`match.groups`](#managed) 也会读取该声明。当网关发现空列表或空条目时会拒绝启动。网关不会根据您的 IdP 检查条目,因此不匹配任何人的条目不会引发警告。
821* **顺序**:将没有 `groups` 列表的上游放在最后。它为所有人提供服务,因此如果排在前面,它会抢在团队自己的上游之前接收该团队的请求。
822
823> [!WARNING]
824>
825> 早于 v2.1.314 的网关在发现 `groups` 时会拒绝启动,因此请在添加它之前升级每个副本。
826>
827> 回滚之前,请删除每个带有 `groups` 列表的上游,以及每个引用该上游的 `upstream_model` 键或定价覆盖,并至少保留一个上游。如果只删除 `groups` 键,该上游将对所有开发者开放。仍引用已删除上游的键或覆盖会导致网关无法启动,并显示 `references unknown upstream`。
828
829##### 开发者不属于任何所列组时会发生什么
830
831如果每个上游都有 `groups` 列表,不属于其中任何组的开发者会看到以下错误,并且网关不会联系任何提供商:
832
833```text theme={null}
834API Error: 400 you aren't in a group that can use this gateway. Ask your administrator to add you to one
835```
836
837请在您的 IdP 中将该开发者添加到所列的某个组,或添加一个没有 `groups` 列表的上游。
838
839网关会在每次令牌刷新时重新读取开发者所属的组。如果您的 IdP 在刷新时未包含组信息,该开发者将不属于任何组:
840
841* **已设置 [`oidc.allowed_groups`](#oidc)**:网关拒绝该刷新,会话结束
842* **否则,如果某个上游没有 `groups` 列表**:该开发者的请求会转到该上游
843* **否则,如果每个上游都有 `groups` 列表**:该开发者的请求会以上述错误失败
844
845如果您的 IdP 的 userinfo 端点返回 groups 声明,且未设置 `oidc.google_groups`,请将 [`oidc.userinfo_fallback`](#oidc) 设置为 `true`,以便从该端点补充组信息。
846
691## 可选部分847## 可选部分
692 848
693### `admin`849### `admin`
782 938
783#### 将费率发送到已登录的客户端939#### 将费率发送到已登录的客户端
784 940
785在网关服务器上使用 v2.1.268 或更高版本时,网关还会将 `pricing` 中的费率作为 [`modelPricing`](https://code.claude.com/docs/zh-CN/settings-reference#modelpricing) 托管设置放入其提供的 [`managed`](#managed) 策略中。随后,被策略匹配的开发者会在 `/usage`、状态栏和 OpenTelemetry 中看到为每个模型 ID 提供服务的第一个上游的 `pricing` 费率。未匹配任何策略的开发者不会收到托管设置,因此其数据保持标价。客户端在 Claude Code v2.1.242 或更高版本中应用该设置。941在网关服务器上使用 v2.1.268 或更高版本时,网关还会将 `pricing` 中的费率作为 [`modelPricing`](https://code.claude.com/docs/zh-CN/settings-reference#modelpricing) 托管设置,放入其提供的 [`managed`](#managed) 策略中。
942
943被某个策略匹配的开发者随后会在 `/usage`、状态栏和 OpenTelemetry 中看到 `pricing` 费率。未匹配任何策略的开发者不会收到托管设置,因此其数据保持按标价计算。客户端在 Claude Code v2.1.242 或更高版本中应用此设置。
786 944
787* 网关添加的内容:除非策略的 `cli` 块已设置 `modelPricing`,否则网关会添加 `multiplier`,并针对客户端可以请求的每个模型 ID,添加为该 ID 提供服务的第一个上游的覆盖行。仅由故障转移上游收取的费率保留在网关上。945* 网关添加的内容:除非策略的 `cli` 块已设置 `modelPricing`,否则网关会添加 `multiplier`,并针对客户端可以请求的每个模型 ID,添加为该 ID 提供服务的第一个上游的覆盖行。仅由故障转移上游收取的费率保留在网关上。
946* 带有 [`groups` 列表](#send-each-team-to-its-own-upstream)的上游:当它是为某个模型 ID 提供服务的第一个上游时,网关不会为该 ID 添加行。开发者随后会看到 Claude Code 自己为该 ID 设定的费率(当 Claude Code 识别该 ID 时,即该模型的标准费率)乘以 `multiplier`。
788* 让某个策略退出:在该策略的 `cli` 块中将 `modelPricing` 设置为 `{}`,其开发者将保持标价。947* 让某个策略退出:在该策略的 `cli` 块中将 `modelPricing` 设置为 `{}`,其开发者将保持标价。
789* 保留策略自身的费率:如果策略的 `cli` 块使用自己的 `multiplier` 或 `overrides` 设置了 `modelPricing`,则该 `modelPricing` 会完整保留,网关不会向其中添加自己的任何费率。948* 保留策略自身的费率:如果策略的 `cli` 块使用自己的 `multiplier` 或 `overrides` 设置了 `modelPricing`,则该 `modelPricing` 会完整保留,网关不会向其中添加自己的任何费率。
790 949
808 967
809### `managed`968### `managed`
810 969
811`managed` 块定义基于 IdP 组或电子邮件域的基于角色的访问策略。策略按顺序评估;选中第一个匹配项,然后将其合并到 `match: {}` 兜底基础层上。这些策略按用户在 `GET /managed/settings` 提供,并使用 ETag/304 缓存。970`managed` 块定义基于 IdP 组或电子邮件域的基于角色的访问策略。策略按顺序评估;默认情况下选择第一个匹配项,然后将其合并到 `match: {}` 兜底基础层上。匹配两个角色策略的用户只会获得第一个,因此除非您[应用所有匹配的策略](#apply-every-matching-policy),否则第二个策略的拒绝规则不会生效。策略按用户在 `GET /managed/settings` 提供,并使用 ETag/304 缓存。
812 971
813```yaml theme={null}972```yaml theme={null}
814managed:973managed:
849 1008
850未匹配任何策略的已通过身份验证的用户将获得网关的默认值,即目录中的所有模型且没有托管设置。如果您希望有一个确定的默认策略,请在最后添加一个 `match: {}` 兜底策略。1009未匹配任何策略的已通过身份验证的用户将获得网关的默认值,即目录中的所有模型且没有托管设置。如果您希望有一个确定的默认策略,请在最后添加一个 `match: {}` 兜底策略。
851 1010
1011请将组织范围的拒绝规则放在 `match: {}` 策略中,因为组策略的规则仅在用户的令牌携带该组时才适用。
1012
852> [!NOTE]1013> [!NOTE]
853>1014>
854> 网关本身不保存用户目录。它根据用户的 IdP 令牌对每个请求进行授权,从令牌的 `groups` 声明中读取组成员身份,并据此评估策略。没有可枚举的名单,也没有需要预先创建的账户,因此也没有 SCIM 端点,因为没有任何内容可供 SCIM 同步。1015> 网关本身不保存用户目录。它根据用户的 IdP 令牌对每个请求进行授权,从令牌的 `groups` 声明中读取组成员身份,并据此评估策略。没有可枚举的名单,也没有需要预先创建的账户,因此也没有 SCIM 端点,因为没有任何内容可供 SCIM 同步。
862>1023>
863> Claude Desktop 遵循[其自身的时间安排](#when-a-policy-change-reaches-claude-desktop)。1024> Claude Desktop 遵循[其自身的时间安排](#when-a-policy-change-reaches-claude-desktop)。
864 1025
1026#### 应用所有匹配的策略
1027
1028匹配多个角色策略的用户只会获得第一个,除非您在 `policies` 旁边设置 `policy_mode: layered`。使用 `layered` 时,与用户匹配的每个策略都会生效,直到第一个 `match: {}` 策略为止。
1029
1030`policy_mode` 要求网关服务器上的 Claude Code 为 v2.1.316 或更高版本。不支持该键的版本的网关在发现该键时会拒绝启动。请在添加该键之前升级每个副本,并在回滚到更早版本之前删除该键。此示例中,一个组失去 `WebFetch`,另一个组获得 Opus:
1031
1032```yaml theme={null}
1033managed:
1034 policy_mode: layered
1035 policies:
1036 - match: { groups: [no-web] }
1037 cli:
1038 permissions: { deny: ["WebFetch"] }
1039 - match: { groups: [opus-users] }
1040 cli:
1041 availableModels: [opus, sonnet]
1042 - match: {}
1043 cli:
1044 availableModels: [sonnet]
1045 enforceAvailableModels: true
1046```
1047
1048下表显示同时属于 `no-web` 和 `opus-users` 的用户在默认的 `first_match` 和 `layered` 下分别收到的内容。
1049
1050| 设置 | `first_match` | `layered` |
1051| - | - | - |
1052| `availableModels` | `sonnet` | `opus`、`sonnet` |
1053| `enforceAvailableModels` | `true` | `true` |
1054| `permissions.deny` | `WebFetch` | `WebFetch` |
1055
1056网关按照与基础层相同的[合并规则](#managed),将每个匹配的策略合并到列在其下方的策略上:
1057
1058* **允许列表、单值以及 `sandbox` 等块**:每一项完整地取自设置了它的、列在最前面的匹配策略,因此两个组的 `availableModels` 列表不会叠加。
1059* **拒绝列表和 hook 数组**:这些在所有匹配的策略之间叠加,因此属于两个组的用户会获得两个组的拒绝规则。
1060* **`env`、`modelOverrides` 和 `skillOverrides`**:条目按名称合并,由设置了该名称的、列在最前面的匹配策略提供其值。
1061* **`desktop` 键**:这些按照[基础 `desktop` 块的规则](#how-a-role-policy-inherits-the-base-desktop-block)合并。
1062
1063> [!WARNING]
1064>
1065> 多个策略叠加后的规则可能比其中任何一个单独给出的规则更宽松。例如,`match: {}` 策略设置了 `sandbox.enabled: true`,一个组的策略设置了 `permissions.allow: ["Bash"]`,另一个组的策略设置了 `sandbox.enabled: false`。同时属于两个组的用户将获得允许 `Bash` 且关闭沙箱的设置。这种情况下,请将允许 `Bash` 的策略列在最前面,并将 `match: {}` 策略的整个 `sandbox` 块复制到其中。
1066
1067使用 `layered` 时,网关会因某些设置而拒绝启动,包括以下设置:
1068
1069* **`!` 模式**:任何策略(包括 `match: {}` 策略)的 `permissions.deny` 或 `permissions.ask` 列表中,`Read` 或 `Edit` 规则里的 [`!` 否定](https://code.claude.com/docs/zh-CN/permissions#special-characters-and-negation)
1070* **兜底策略之外对 hook 的限制**:除 `match: {}` 以外的任何策略中的 `disableAllHooks`、`allowedHttpHookUrls` 或 `httpHookAllowedEnvVars`
1071
865#### 让会话在策略允许的模型上启动1072#### 让会话在策略允许的模型上启动
866 1073
867如果 `availableModels` 未包含 Claude Code 的默认模型,会话将收到 `400` 响应,直到开发者选择一个列出的模型(例如使用 `/model`)。在网关会话中,默认模型是 `opus` 别名解析到的 Opus 模型,而单独使用 `availableModels` 不会改变它。1074如果 `availableModels` 未包含 Claude Code 的默认模型,会话将收到 `400` 响应,直到开发者选择一个列出的模型(例如使用 `/model`)。在网关会话中,默认模型是 `opus` 别名解析到的 Opus 模型,而单独使用 `availableModels` 不会改变它。