diff --git a/src/strands/multiagent/a2a/server.py b/src/strands/multiagent/a2a/server.py index fd90e9787..0a3269ca1 100644 --- a/src/strands/multiagent/a2a/server.py +++ b/src/strands/multiagent/a2a/server.py @@ -105,6 +105,7 @@ def __init__( push_sender=push_sender, ) self._agent_skills = skills + self._agent_card_url: str | None = None logger.info("Strands' integration with A2A is experimental. Be aware of frequent breaking changes.") def _parse_public_url(self, url: str) -> tuple[str, str]: @@ -148,7 +149,7 @@ def public_agent_card(self) -> AgentCard: return AgentCard( name=self.name, description=self.description, - url=self.http_url, + url=self.agent_card_url, version=self.version, skills=self.agent_skills, default_input_modes=["text"], @@ -170,6 +171,24 @@ def _get_skills_from_tools(self) -> list[AgentSkill]: for config in self.strands_agent.tool_registry.get_all_tools_config().values() ] + @property + def agent_card_url(self) -> str: + """Get the URL advertised in the AgentCard. + + Defaults to http_url. Can be overridden to advertise a custom URL + (e.g., without trailing slash or with a different base). + """ + return self._agent_card_url if self._agent_card_url is not None else self.http_url + + @agent_card_url.setter + def agent_card_url(self, url: str) -> None: + """Override the URL advertised in the AgentCard. + + Args: + url: The URL to advertise in the AgentCard. + """ + self._agent_card_url = url + @property def agent_skills(self) -> list[AgentSkill]: """Get the list of skills this agent provides.""" diff --git a/tests/strands/multiagent/a2a/test_server.py b/tests/strands/multiagent/a2a/test_server.py index aeb882b19..7e79b4557 100644 --- a/tests/strands/multiagent/a2a/test_server.py +++ b/tests/strands/multiagent/a2a/test_server.py @@ -600,6 +600,26 @@ def test_public_agent_card_with_http_url(mock_strands_agent): assert card.description == "A test agent for unit testing" +def test_agent_card_url_defaults_to_http_url(mock_strands_agent): + """Test that agent_card_url defaults to http_url.""" + mock_strands_agent.tool_registry.get_all_tools_config.return_value = {} + + a2a_agent = A2AServer(mock_strands_agent, http_url="https://my-alb.amazonaws.com/agent1", skills=[]) + assert a2a_agent.agent_card_url == "https://my-alb.amazonaws.com/agent1/" # Adds trailing slash at the end + + +def test_agent_card_url_override(mock_strands_agent): + """Test that agent_card_url can be overridden to a custom value.""" + mock_strands_agent.tool_registry.get_all_tools_config.return_value = {} + + a2a_agent = A2AServer(mock_strands_agent, http_url="https://my-alb.amazonaws.com/agent1", skills=[]) + a2a_agent.agent_card_url = "https://my-alb.amazonaws.com/agent1" # Override to URL without trailing slash + + assert a2a_agent.agent_card_url == "https://my-alb.amazonaws.com/agent1" + card = a2a_agent.public_agent_card + assert card.url == "https://my-alb.amazonaws.com/agent1" + + def test_to_starlette_app_with_mounting(mock_strands_agent): """Test that to_starlette_app creates mounted app when mount_path exists.""" mock_strands_agent.tool_registry.get_all_tools_config.return_value = {}