Bedrock delegation API mode routing fixes
Cluster 49095 · agent. Data as of
Nothing open on GitHub. Fix merged in #51724. Check it covers your case.
The short answer
- Known?
- Yes. 5 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #51724. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #51724. That is separate from the fix event. - Still open
- Nothing open on GitHub.
Multiple fixes targeting how the delegation system routes Bedrock provider requests, specifically around selecting the correct API mode (converse) and target model for Bedrock subagents. Includes a concern about silent fallback to OpenRouter when Bedrock delegation provider is misconfigured.
Open issues0
Open PRs0
Fixes on record
-
#51724 fix(delegation): use target_model for bedrock api_mode routing (#49095)
files:
hermes_cli/runtime_provider.py,tests/hermes_cli/test_runtime_provider_resolution.pyShow the diff
-
hermes_cli/runtime_provider.py@@ -1750,7 +1750,7 @@ def resolve_runtime_provider( # Dual-path routing: Claude models use AnthropicBedrock SDK for full # feature parity (prompt caching, thinking budgets, adaptive thinking). # Non-Claude models use the Converse API for multi-model support. - _current_model = str(model_cfg.get("default") or "").strip() + _current_model = str(target_model or model_cfg.get("default") or "").strip() if is_anthropic_bedrock_model(_current_model): # Claude on Bedrock → AnthropicBedrock SDK → anthropic_messages path runtime = { -
tests/hermes_cli/test_runtime_provider_resolution.py@@ -2835,3 +2835,61 @@ def test_host_derived_key_helper_basic_cases(): for k in ("DEEPSEEK_API_KEY", "GROQ_API_KEY", "MISTRAL_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY"): _os.environ.pop(k, None) + + +def _patch_bedrock(monkeypatch, config_default=""): + """Stub the bedrock_adapter helpers resolve_runtime_provider imports. + + Leaves the real ``is_anthropic_bedrock_model`` in place so the dual-path + routing decision is exercised for real. ``config_default`` is the persisted + ``model.default`` — kept non-Claude here to prove ``target_model`` (not the + stale config default) drives the api_mode decision. + """ + import agent.bedrock_adapter as ba + + monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "bedrock") + monkeypatch.setattr(rp, "_get_model_config", lambda: {"default": config_default}) + monkeypatch.setattr(rp, "load_config", lambda: {"bedrock": {}}) + monkeypatch.setattr(ba, "has_aws_credentials", lambda: True) + monkeypatch.setattr(ba, "resolve_aws_auth_env_var", lambda: "AWS_PROFILE") + monkeypatch.setattr(ba, "resolve_bedrock_region", lambda: "eu-north-1") + + +def test_resolve_runtime_provider_bedrock_claude_target_model_uses_anthropic_messages(monkeypatch): + """Claude-on-Bedrock delegation must route through the AnthropicBedrock SDK. + + Regression for #49095: the bedrock branch derived api_mode from the stale + persisted ``model.default`` instead of ``target_model``. When delegation + targets a Claude model but the parent's default is non-Claude, the wrong + branch (Converse) was picked, and the child silently fell back to + openrouter/free. ``target_model`` must win so Claude keeps the + anthropic_messages path (prompt caching, thinking budgets). + """ + _patch_bedrock(monkeypatch, config_default="amazon.nova-pro-v1:0") + + resolved = rp.resolve_runtime_provider( + requested="bedrock", + target_model="global.anthropic.claude-sonnet-4-6", + ) + + assert resolved["provider"] == "bedrock" + assert resolved["api_mode"] == "anthropic_messages" + assert resolved.get("bedrock_anthropic") is True + + +def test_resolve_runtime_provider_bedrock_nonclaude_target_model_uses_converse(monkeypatch): + """Non-Claude Bedrock target stays on the Converse API path. + + Confirms the target_model fix doesn't over-correct: a Nova target must NOT + be forced onto anthropic_messages even when the persisted default is Claude. + """ + _patch_bedrock(monkeypatch, config_default="global.anthropic.claude-sonnet-4-6") + + resolved = rp.resolve_runtime_provider( + requested="bedrock", + target_model="amazon.nova-pro-v1:0", + ) + + assert resolved["provider"] == "bedrock" + assert resolved["api_mode"] == "bedrock_converse" + assert resolved.get("bedrock_anthropic") is not True
-
3 PRs closed without merging
From the close comments: done elsewhere 2 · duplicate 1
-
#49117 fix(delegation): force bedrock_converse api_mode for bedrock delegation provider · done elsewhere →
#51724,#49095 -
#49155 fix(delegation): use target_model for bedrock api_mode routing (#49095) · done elsewhere →
#51724 -
#49375 fix(delegate): route bedrock subagents through converse mode · duplicate →
#49117
Closed issues · 1
- Closed#49095fix(delegation): bedrock delegation.provider silently falls back to openrouter/free
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- agent
- Merged PRs
- #51724
- Closed issues
- 1
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 24 Jun 2026