You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-03-30 10:57:20 -07:00
feat: Allow user to specify protocol for A2A RPC URL in to_a2a utility
this fixes https://github.com/google/adk-python/issues/2405 PiperOrigin-RevId: 797958771
This commit is contained in:
committed by
Copybara-Service
parent
ccab076ace
commit
157f73181d
@@ -39,11 +39,17 @@ from ...memory.in_memory_memory_service import InMemoryMemoryService
|
||||
from ...runners import Runner
|
||||
from ...sessions.in_memory_session_service import InMemorySessionService
|
||||
from ..executor.a2a_agent_executor import A2aAgentExecutor
|
||||
from ..experimental import a2a_experimental
|
||||
from .agent_card_builder import AgentCardBuilder
|
||||
|
||||
|
||||
@a2a_experimental
|
||||
def to_a2a(
|
||||
agent: BaseAgent, *, host: str = "localhost", port: int = 8000
|
||||
agent: BaseAgent,
|
||||
*,
|
||||
host: str = "localhost",
|
||||
port: int = 8000,
|
||||
protocol: str = "http",
|
||||
) -> Starlette:
|
||||
"""Convert an ADK agent to a A2A Starlette application.
|
||||
|
||||
@@ -51,13 +57,14 @@ def to_a2a(
|
||||
agent: The ADK agent to convert
|
||||
host: The host for the A2A RPC URL (default: "localhost")
|
||||
port: The port for the A2A RPC URL (default: 8000)
|
||||
protocol: The protocol for the A2A RPC URL (default: "http")
|
||||
|
||||
Returns:
|
||||
A Starlette application that can be run with uvicorn
|
||||
|
||||
Example:
|
||||
agent = MyAgent()
|
||||
app = to_a2a(agent, host="localhost", port=8000)
|
||||
app = to_a2a(agent, host="localhost", port=8000, protocol="http")
|
||||
# Then run with: uvicorn module:app --host localhost --port 8000
|
||||
"""
|
||||
# Set up ADK logging to ensure logs are visible when using uvicorn directly
|
||||
@@ -87,7 +94,7 @@ def to_a2a(
|
||||
)
|
||||
|
||||
# Build agent card
|
||||
rpc_url = f"http://{host}:{port}/"
|
||||
rpc_url = f"{protocol}://{host}:{port}/"
|
||||
card_builder = AgentCardBuilder(
|
||||
agent=agent,
|
||||
rpc_url=rpc_url,
|
||||
|
||||
@@ -123,7 +123,7 @@ class TestToA2A:
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.InMemoryTaskStore")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.AgentCardBuilder")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.Starlette")
|
||||
def test_to_a2a_custom_host_port(
|
||||
def test_to_a2a_custom_host_port_protocol(
|
||||
self,
|
||||
mock_starlette_class,
|
||||
mock_card_builder_class,
|
||||
@@ -131,7 +131,7 @@ class TestToA2A:
|
||||
mock_request_handler_class,
|
||||
mock_agent_executor_class,
|
||||
):
|
||||
"""Test to_a2a with custom host and port."""
|
||||
"""Test to_a2a with custom host, port, and protocol."""
|
||||
# Arrange
|
||||
mock_app = Mock(spec=Starlette)
|
||||
mock_starlette_class.return_value = mock_app
|
||||
@@ -145,12 +145,14 @@ class TestToA2A:
|
||||
mock_card_builder_class.return_value = mock_card_builder
|
||||
|
||||
# Act
|
||||
result = to_a2a(self.mock_agent, host="example.com", port=9000)
|
||||
result = to_a2a(
|
||||
self.mock_agent, host="example.com", port=9000, protocol="https"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result == mock_app
|
||||
mock_card_builder_class.assert_called_once_with(
|
||||
agent=self.mock_agent, rpc_url="http://example.com:9000/"
|
||||
agent=self.mock_agent, rpc_url="https://example.com:9000/"
|
||||
)
|
||||
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.A2aAgentExecutor")
|
||||
@@ -704,3 +706,110 @@ class TestToA2A:
|
||||
mock_card_builder_class.assert_called_once_with(
|
||||
agent=self.mock_agent, rpc_url="http://192.168.1.1:8000/"
|
||||
)
|
||||
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.A2aAgentExecutor")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.DefaultRequestHandler")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.InMemoryTaskStore")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.AgentCardBuilder")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.Starlette")
|
||||
def test_to_a2a_with_https_protocol(
|
||||
self,
|
||||
mock_starlette_class,
|
||||
mock_card_builder_class,
|
||||
mock_task_store_class,
|
||||
mock_request_handler_class,
|
||||
mock_agent_executor_class,
|
||||
):
|
||||
"""Test to_a2a with HTTPS protocol."""
|
||||
# Arrange
|
||||
mock_app = Mock(spec=Starlette)
|
||||
mock_starlette_class.return_value = mock_app
|
||||
mock_task_store = Mock(spec=InMemoryTaskStore)
|
||||
mock_task_store_class.return_value = mock_task_store
|
||||
mock_agent_executor = Mock(spec=A2aAgentExecutor)
|
||||
mock_agent_executor_class.return_value = mock_agent_executor
|
||||
mock_request_handler = Mock(spec=DefaultRequestHandler)
|
||||
mock_request_handler_class.return_value = mock_request_handler
|
||||
mock_card_builder = Mock(spec=AgentCardBuilder)
|
||||
mock_card_builder_class.return_value = mock_card_builder
|
||||
|
||||
# Act
|
||||
result = to_a2a(self.mock_agent, protocol="https")
|
||||
|
||||
# Assert
|
||||
assert result == mock_app
|
||||
mock_card_builder_class.assert_called_once_with(
|
||||
agent=self.mock_agent, rpc_url="https://localhost:8000/"
|
||||
)
|
||||
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.A2aAgentExecutor")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.DefaultRequestHandler")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.InMemoryTaskStore")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.AgentCardBuilder")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.Starlette")
|
||||
def test_to_a2a_with_custom_protocol(
|
||||
self,
|
||||
mock_starlette_class,
|
||||
mock_card_builder_class,
|
||||
mock_task_store_class,
|
||||
mock_request_handler_class,
|
||||
mock_agent_executor_class,
|
||||
):
|
||||
"""Test to_a2a with custom protocol."""
|
||||
# Arrange
|
||||
mock_app = Mock(spec=Starlette)
|
||||
mock_starlette_class.return_value = mock_app
|
||||
mock_task_store = Mock(spec=InMemoryTaskStore)
|
||||
mock_task_store_class.return_value = mock_task_store
|
||||
mock_agent_executor = Mock(spec=A2aAgentExecutor)
|
||||
mock_agent_executor_class.return_value = mock_agent_executor
|
||||
mock_request_handler = Mock(spec=DefaultRequestHandler)
|
||||
mock_request_handler_class.return_value = mock_request_handler
|
||||
mock_card_builder = Mock(spec=AgentCardBuilder)
|
||||
mock_card_builder_class.return_value = mock_card_builder
|
||||
|
||||
# Act
|
||||
result = to_a2a(self.mock_agent, protocol="ws")
|
||||
|
||||
# Assert
|
||||
assert result == mock_app
|
||||
mock_card_builder_class.assert_called_once_with(
|
||||
agent=self.mock_agent, rpc_url="ws://localhost:8000/"
|
||||
)
|
||||
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.A2aAgentExecutor")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.DefaultRequestHandler")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.InMemoryTaskStore")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.AgentCardBuilder")
|
||||
@patch("google.adk.a2a.utils.agent_to_a2a.Starlette")
|
||||
def test_to_a2a_with_all_custom_parameters(
|
||||
self,
|
||||
mock_starlette_class,
|
||||
mock_card_builder_class,
|
||||
mock_task_store_class,
|
||||
mock_request_handler_class,
|
||||
mock_agent_executor_class,
|
||||
):
|
||||
"""Test to_a2a with all custom parameters."""
|
||||
# Arrange
|
||||
mock_app = Mock(spec=Starlette)
|
||||
mock_starlette_class.return_value = mock_app
|
||||
mock_task_store = Mock(spec=InMemoryTaskStore)
|
||||
mock_task_store_class.return_value = mock_task_store
|
||||
mock_agent_executor = Mock(spec=A2aAgentExecutor)
|
||||
mock_agent_executor_class.return_value = mock_agent_executor
|
||||
mock_request_handler = Mock(spec=DefaultRequestHandler)
|
||||
mock_request_handler_class.return_value = mock_request_handler
|
||||
mock_card_builder = Mock(spec=AgentCardBuilder)
|
||||
mock_card_builder_class.return_value = mock_card_builder
|
||||
|
||||
# Act
|
||||
result = to_a2a(
|
||||
self.mock_agent, host="api.example.com", port=443, protocol="https"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result == mock_app
|
||||
mock_card_builder_class.assert_called_once_with(
|
||||
agent=self.mock_agent, rpc_url="https://api.example.com:443/"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user