# NousResearch/hermes-agent · Bedrock delegation API mode routing fixes

## Open now

- 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.

## TL;DR

- 5 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 3 PR(s) closed without merging.
- A fix was merged to main in PR #51724. Verify it addresses your case.
- **Recommended:** read PR #51724 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-51724`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.40`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #49095: fix(delegation): bedrock delegation.provider silently falls back to openrouter/free

## Prior & competing PRs

- **#51724: fix(delegation): use target_model for bedrock api_mode routing (#49095)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `hermes_cli/runtime_provider.py`, `tests/hermes_cli/test_runtime_provider_resolution.py`
  - fix hunks:
  - `hermes_cli/runtime_provider.py`

    ```diff
    @@ -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`

    ```diff
    @@ -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
    ```
- **#49117: fix(delegation): force bedrock_converse api_mode for bedrock delegation provider**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#51724`, `#49095`
- **#49155: fix(delegation): use target_model for bedrock api_mode routing (#49095)**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#51724`
- **#49375: fix(delegate): route bedrock subagents through converse mode**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#49117`

## Fix status

- Merged to main in PR #51724 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-24`.
- Subsystem: `agent`
