Skip to content
Open
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
10 changes: 8 additions & 2 deletions src/strands/experimental/bidi/models/nova_sonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import json
import logging
import uuid
from importlib.metadata import PackageNotFoundError, version
from typing import Any, AsyncGenerator, cast

import boto3
Expand Down Expand Up @@ -96,6 +97,11 @@
NOVA_TEXT_CONFIG = {"mediaType": "text/plain"}
NOVA_TOOL_CONFIG = {"mediaType": "application/json"}

try:
_STRANDS_USER_AGENT_EXTRA = f"lib/strands-agents#{version('strands-agents')}"
except PackageNotFoundError:
_STRANDS_USER_AGENT_EXTRA = "lib/strands-agents"


class BidiNovaSonicModel(BidiModel):
"""Nova Sonic implementation for bidirectional streaming.
Expand Down Expand Up @@ -259,13 +265,13 @@ async def start(
aws_access_key_id=credentials.access_key,
aws_secret_access_key=credentials.secret_key,
aws_session_token=credentials.token,
user_agent_extra=_STRANDS_USER_AGENT_EXTRA,
)

self.client = BedrockRuntimeClient(config=config)
logger.debug("region=<%s> | nova sonic client initialized", self.region)

client = BedrockRuntimeClient(config=config)
self._stream = await client.invoke_model_with_bidirectional_stream(
self._stream = await self.client.invoke_model_with_bidirectional_stream(
InvokeModelWithBidirectionalStreamOperationInput(model_id=self.model_id)
)
logger.debug("region=<%s> | nova sonic client initialized", self.region)
Expand Down
17 changes: 17 additions & 0 deletions tests/strands/experimental/bidi/models/test_nova_sonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@ async def test_model_initialization(model_id, boto_session):
assert model._connection_id is None


@pytest.mark.asyncio
async def test_start_sets_strands_user_agent_on_bedrock_runtime_client(model_id, boto_session, mock_stream):
"""Always set the Strands user agent marker on the generated Bedrock Runtime client."""
with patch("strands.experimental.bidi.models.nova_sonic.BedrockRuntimeClient") as mock_cls:
mock_instance = AsyncMock()
mock_instance.invoke_model_with_bidirectional_stream = AsyncMock(return_value=mock_stream)
mock_cls.return_value = mock_instance

model = BidiNovaSonicModel(model_id=model_id, client_config={"boto_session": boto_session})

await model.start()

assert mock_cls.call_count == 1
config = mock_cls.call_args.kwargs["config"]
assert config.user_agent_extra.startswith("lib/strands-agents")


# Audio Configuration Tests


Expand Down