Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,20 @@ def _workload_identity_credentials(wif: dict[str, Any]) -> WorkloadIdentityCrede
kwargs["scope"] = wif["scope"]
return WorkloadIdentityCredentials(**kwargs)

def _resolve_model(self, model: str | None) -> str:
"""Resolve the effective model id; Bedrock rejects a bare id, so require its prefix."""
resolved = model or self.default_model
# Valid Bedrock ids either start with the ``anthropic.`` provider prefix or carry a
# region/profile prefix as a dotted component (e.g. ``us.anthropic.``, ``global.anthropic.``).
is_bedrock_model_id = resolved.startswith("anthropic.") or ".anthropic." in resolved
if self.platform == "bedrock" and not is_bedrock_model_id:
raise AnthropicError(
f"Model {resolved!r} is not a valid Amazon Bedrock model id. Bedrock ids carry a "
"provider/region prefix (e.g. 'global.anthropic.claude-opus-4-6-v1'); set one via "
"the 'model' argument or the connection's extra['model']."
)
return resolved

def _require_first_party(self, feature: str) -> None:
if self.platform not in FIRST_PARTY_PLATFORMS:
raise AnthropicError(
Expand Down Expand Up @@ -348,7 +362,7 @@ def create_message(
:param system: Optional system prompt.
"""
params: dict[str, Any] = {
"model": model or self.default_model,
"model": self._resolve_model(model),
"max_tokens": max_tokens,
"messages": messages,
**kwargs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,40 @@ def test_create_agent_uses_connection_model(self):
hook.create_agent(name="a")
assert client.beta.agents.create.call_args.kwargs["model"] == "claude-sonnet-4-6"

@pytest.mark.parametrize(
"model",
[None, "my-anthropic.model"], # bare default id and a substring that is not a real prefix
)
def test_bedrock_rejects_invalid_model_id(self, model):
extra = {"platform": "bedrock", **({"model": model} if model else {})}
hook, client = _make_hook(extra=extra)
with pytest.raises(AnthropicError, match="not a valid Amazon Bedrock model id"):
hook.create_message([{"role": "user", "content": "hi"}])
client.messages.create.assert_not_called()

@pytest.mark.parametrize(
("platform", "model", "expected"),
[
(
"bedrock",
"anthropic.claude-sonnet-4-5-20250929-v1:0",
"anthropic.claude-sonnet-4-5-20250929-v1:0",
),
("bedrock", "global.anthropic.claude-opus-4-6-v1", "global.anthropic.claude-opus-4-6-v1"),
(
"bedrock",
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
),
("vertex", None, DEFAULT_MODEL), # non-Bedrock platforms skip the guard
],
)
def test_accepts_valid_model_id(self, platform, model, expected):
extra = {"platform": platform, **({"model": model} if model else {})}
hook, client = _make_hook(extra=extra)
hook.create_message([{"role": "user", "content": "hi"}])
assert client.messages.create.call_args.kwargs["model"] == expected


class TestManagedAgentsHook:
def _hook_with_client(self, extra=None):
Expand Down