[PR #6773] [MERGED] [proxy] match Bedrock provider models against the normalized request model #29879

Closed
opened 2026-08-05 08:09:17 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6773
Author: @mlsmaycon
Created: 7/15/2026
Status: Merged
Merged: 7/21/2026
Merged by: @mlsmaycon

Base: mainHead: fix/agentnet-bedrock-model-normalization


📝 Commits (2)

  • 58e0167 [proxy] match Bedrock provider models against the normalized request model
  • 009e907 Merge branch 'main' into fix/agentnet-bedrock-model-normalization

📊 Changes

4 files changed (+100 additions, -0 deletions)

View changed files

proxy/internal/llm/bedrock_model.go (+38 -0)
proxy/internal/llm/bedrock_model_test.go (+23 -0)
proxy/internal/middleware/builtin/llm_router/bedrock_route_test.go (+30 -0)
📝 proxy/internal/middleware/builtin/llm_router/middleware.go (+9 -0)

📄 Description

Describe your changes

Native AWS Bedrock requests carry the model in the URL path as a cross-region inference-profile id (e.g. us.anthropic.claude-haiku-4-5). The request parser normalizes that to the catalog key (anthropic.claude-haiku-4-5) before the router runs, but the router matched it against the operator's registered provider models with exact string equality. So a Bedrock provider registered with the id Bedrock actually uses (us.anthropic…) never matched a normalized request → the request denied with llm_policy.model_not_routable ("no provider configured for model …"). Only a provider registered with the already-stripped catalog id worked, which is not how Bedrock ids appear.

Fix: introduce a single shared llm.NormalizeBedrockModel (the same ARN/region-prefix/version-suffix stripping the parser already does) and, in the router's routeClaimsModel, normalize a Bedrock route's candidate models before comparing. Now a Bedrock provider registered with either the raw inference-profile id or the normalized catalog id matches the request. Non-Bedrock routes keep exact matching.

Surfaced by the new native-Bedrock e2e (WireBedrock, /model/{id}/invoke); the old e2e used the Anthropic body shape, which never normalized either side and so hid this.

The request parser keeps its own identical normalizer for now; de-duplicating it onto llm.NormalizeBedrockModel is a trivial follow-up.

N/A — follow-up to the Agent Network Bedrock support / model-allowlist work.

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Internal routing correctness fix; no user-facing surface change.

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Tests

  • proxy/internal/llm: NormalizeBedrockModel unit cases (region prefixes, version suffixes, ARN).
  • proxy/internal/middleware/builtin/llm_router: routeClaimsModel matches a Bedrock route registered with the raw us.anthropic… id against a normalized request model; non-Bedrock routes still match exactly.

Note: full through-tunnel e2e verification of this (the native-Bedrock TestProvidersMatrix/bedrock) also needs the DNS lazy-connection warm-up (separate PR) to get the client past the proxy-peer gate; they converge once both land.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Amazon Bedrock model matching across ARN formats, regional prefixes, and version or throughput suffixes.
    • Bedrock routes now correctly match equivalent model identifiers even when requests and route configurations use different formats.
    • Non-Bedrock model matching remains exact.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6773 **Author:** [@mlsmaycon](https://github.com/mlsmaycon) **Created:** 7/15/2026 **Status:** ✅ Merged **Merged:** 7/21/2026 **Merged by:** [@mlsmaycon](https://github.com/mlsmaycon) **Base:** `main` ← **Head:** `fix/agentnet-bedrock-model-normalization` --- ### 📝 Commits (2) - [`58e0167`](https://github.com/netbirdio/netbird/commit/58e01678d326090f7245f0a87fa46193587cd1fc) [proxy] match Bedrock provider models against the normalized request model - [`009e907`](https://github.com/netbirdio/netbird/commit/009e9070a447a198eeaef5f17bfa98a3bef2c2e9) Merge branch 'main' into fix/agentnet-bedrock-model-normalization ### 📊 Changes **4 files changed** (+100 additions, -0 deletions) <details> <summary>View changed files</summary> ➕ `proxy/internal/llm/bedrock_model.go` (+38 -0) ➕ `proxy/internal/llm/bedrock_model_test.go` (+23 -0) ➕ `proxy/internal/middleware/builtin/llm_router/bedrock_route_test.go` (+30 -0) 📝 `proxy/internal/middleware/builtin/llm_router/middleware.go` (+9 -0) </details> ### 📄 Description ## Describe your changes Native AWS Bedrock requests carry the model in the URL path as a cross-region inference-profile id (e.g. `us.anthropic.claude-haiku-4-5`). The request parser normalizes that to the catalog key (`anthropic.claude-haiku-4-5`) before the router runs, but the router matched it against the operator's registered provider models with exact string equality. So a Bedrock provider registered with the id Bedrock actually uses (`us.anthropic…`) never matched a normalized request → the request denied with `llm_policy.model_not_routable` ("no provider configured for model …"). Only a provider registered with the already-stripped catalog id worked, which is not how Bedrock ids appear. Fix: introduce a single shared `llm.NormalizeBedrockModel` (the same ARN/region-prefix/version-suffix stripping the parser already does) and, in the router's `routeClaimsModel`, normalize a **Bedrock** route's candidate models before comparing. Now a Bedrock provider registered with either the raw inference-profile id or the normalized catalog id matches the request. Non-Bedrock routes keep exact matching. Surfaced by the new native-Bedrock e2e (`WireBedrock`, `/model/{id}/invoke`); the old e2e used the Anthropic body shape, which never normalized either side and so hid this. The request parser keeps its own identical normalizer for now; de-duplicating it onto `llm.NormalizeBedrockModel` is a trivial follow-up. ## Issue ticket number and link N/A — follow-up to the Agent Network Bedrock support / model-allowlist work. ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) - [x] This change does **not** modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — **OR** I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first). > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) Internal routing correctness fix; no user-facing surface change. ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: https://github.com/netbirdio/docs/pull/__ ## Tests - `proxy/internal/llm`: `NormalizeBedrockModel` unit cases (region prefixes, version suffixes, ARN). - `proxy/internal/middleware/builtin/llm_router`: `routeClaimsModel` matches a Bedrock route registered with the raw `us.anthropic…` id against a normalized request model; non-Bedrock routes still match exactly. Note: full through-tunnel e2e verification of this (the native-Bedrock `TestProvidersMatrix/bedrock`) also needs the DNS lazy-connection warm-up (separate PR) to get the client past the proxy-peer gate; they converge once both land. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Amazon Bedrock model matching across ARN formats, regional prefixes, and version or throughput suffixes. * Bedrock routes now correctly match equivalent model identifiers even when requests and route configurations use different formats. * Non-Bedrock model matching remains exact. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 08:09:17 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#29879