mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(run_agent): preserve dotted Bedrock inference-profile model IDs (#11976)
Bedrock rejects ``global-anthropic-claude-opus-4-7`` with ``HTTP 400:
The provided model identifier is invalid`` because its inference
profile IDs embed structural dots
(``global.anthropic.claude-opus-4-7``) that ``normalize_model_name``
was converting to hyphens. ``AIAgent._anthropic_preserve_dots`` did
not include ``bedrock`` in its provider allowlist, so every Claude-on-
Bedrock request through the AnthropicBedrock SDK path shipped with
the mangled model ID and failed.
Root cause
----------
``run_agent.py:_anthropic_preserve_dots`` (previously line 6589)
controls whether ``agent.anthropic_adapter.normalize_model_name``
converts dots to hyphens. The function listed Alibaba, MiniMax,
OpenCode Go/Zen and ZAI but not Bedrock, so when a user set
``provider: bedrock`` with a dotted inference-profile model the flag
returned False and ``normalize_model_name`` mangled every dot in the
ID. All four call sites in run_agent.py
(``build_anthropic_kwargs`` + three fallback / review / summary paths
at lines 6707, 7343, 8408, 8440) read from this same helper.
The bug shape matches #5211 for opencode-go, which was fixed in commit
f77be22c by extending this same allowlist.
Fix
---
* Add ``"bedrock"`` to the provider allowlist.
* Add ``"bedrock-runtime."`` to the base-URL heuristic as
defense-in-depth, so a custom-provider-shaped config with
``base_url: https://bedrock-runtime.<region>.amazonaws.com`` also
takes the preserve-dots path even if ``provider`` isn't explicitly
set to ``"bedrock"``. This mirrors how the code downstream at
run_agent.py:759 already treats either signal as "this is Bedrock".
Bedrock model ID shapes covered
-------------------------------
| Shape | Preserved |
| --- | --- |
| ``global.anthropic.claude-opus-4-7`` (reporter's exact ID) | ✓ |
| ``us.anthropic.claude-sonnet-4-5-20250929-v1:0`` | ✓ |
| ``apac.anthropic.claude-haiku-4-5`` | ✓ |
| ``anthropic.claude-3-5-sonnet-20241022-v2:0`` (foundation) | ✓ |
| ``eu.anthropic.claude-3-5-sonnet`` (regional inference profile) | ✓ |
Non-Claude Bedrock models (Nova, Llama, DeepSeek) take the
``bedrock_converse`` / boto3 path which does not call
``normalize_model_name``, so they were never affected by this bug
and remain unaffected by the fix.
Narrow scope — explicitly not changed
-------------------------------------
* ``bedrock_converse`` path (non-Claude Bedrock models) — already
correct; no ``normalize_model_name`` in that pipeline.
* Provider aliases (``aws``, ``aws-bedrock``, ``amazon``,
``amazon-bedrock``) — if a user bypasses the alias-normalization
pipeline and passes ``provider="aws"`` directly, the base-URL
heuristic still catches it because Bedrock always uses a
``bedrock-runtime.`` endpoint. Adding the aliases themselves to the
provider set is cheap but would be scope creep for this fix.
* No other places in ``agent/anthropic_adapter.py`` mangle dots, so
the fix is confined to ``_anthropic_preserve_dots``.
Regression coverage
-------------------
``tests/agent/test_bedrock_integration.py`` gains three new classes:
* ``TestBedrockPreserveDotsFlag`` (5 tests): flag returns True for
``provider="bedrock"`` and for Bedrock runtime URLs (us-east-1 and
ap-northeast-2 — the reporter's region); returns False for non-
Bedrock AWS URLs like ``s3.us-east-1.amazonaws.com``; canary that
Anthropic-native still returns False.
* ``TestBedrockModelNameNormalization`` (5 tests): every documented
Bedrock model-ID shape survives ``normalize_model_name`` with the
flag on; inverse canary pins that ``preserve_dots=False`` still
mangles (so a future refactor can't decouple the flag from its
effect).
* ``TestBedrockBuildAnthropicKwargsEndToEnd`` (2 tests): integration
through ``build_anthropic_kwargs`` shows the reporter's exact model
ID ends up unmangled in the outgoing kwargs.
Three of the new flag tests fail on unpatched ``origin/main`` with
``assert False is True`` (preserve-dots returning False for Bedrock),
confirming the regression is caught.
Validation
----------
``source venv/bin/activate && python -m pytest
tests/agent/test_bedrock_integration.py tests/agent/test_minimax_provider.py
-q`` -> 84 passed (40 new bedrock tests + 44 pre-existing, including
the minimax canaries that pin the pattern this fix mirrors).
CI-aligned broad suite: 12827 passed, 39 skipped, 19 pre-existing
baseline failures (all reproduce on clean ``origin/main``; none in
the touched code path).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
323e827f4a
commit
1cf1016e72
2 changed files with 194 additions and 3 deletions
26
run_agent.py
26
run_agent.py
|
|
@ -6894,11 +6894,31 @@ class AIAgent:
|
|||
Alibaba/DashScope keeps dots (e.g. qwen3.5-plus).
|
||||
MiniMax keeps dots (e.g. MiniMax-M2.7).
|
||||
OpenCode Go/Zen keeps dots for non-Claude models (e.g. minimax-m2.5-free).
|
||||
ZAI/Zhipu keeps dots (e.g. glm-4.7, glm-5.1)."""
|
||||
if (getattr(self, "provider", "") or "").lower() in {"alibaba", "minimax", "minimax-cn", "opencode-go", "opencode-zen", "zai"}:
|
||||
ZAI/Zhipu keeps dots (e.g. glm-4.7, glm-5.1).
|
||||
AWS Bedrock uses dotted inference-profile IDs
|
||||
(e.g. ``global.anthropic.claude-opus-4-7``,
|
||||
``us.anthropic.claude-sonnet-4-5-20250929-v1:0``) and rejects
|
||||
the hyphenated form with
|
||||
``HTTP 400 The provided model identifier is invalid``.
|
||||
Regression for #11976; mirrors the opencode-go fix for #5211
|
||||
(commit f77be22c), which extended this same allowlist."""
|
||||
if (getattr(self, "provider", "") or "").lower() in {
|
||||
"alibaba", "minimax", "minimax-cn",
|
||||
"opencode-go", "opencode-zen",
|
||||
"zai", "bedrock",
|
||||
}:
|
||||
return True
|
||||
base = (getattr(self, "base_url", "") or "").lower()
|
||||
return "dashscope" in base or "aliyuncs" in base or "minimax" in base or "opencode.ai/zen/" in base or "bigmodel.cn" in base
|
||||
return (
|
||||
"dashscope" in base
|
||||
or "aliyuncs" in base
|
||||
or "minimax" in base
|
||||
or "opencode.ai/zen/" in base
|
||||
or "bigmodel.cn" in base
|
||||
# AWS Bedrock runtime endpoints — defense-in-depth when
|
||||
# ``provider`` is unset but ``base_url`` still names Bedrock.
|
||||
or "bedrock-runtime." in base
|
||||
)
|
||||
|
||||
def _is_qwen_portal(self) -> bool:
|
||||
"""Return True when the base URL targets Qwen Portal."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue