Skip to content

Commit 5d22186

Browse files
fix: wrong method name for ExtendedAgentCard endpoint in JsonRpc compat version (#931)
# Description The correct method name for the ExtendedAgentCard endpoint in JsonRpc v.0.3.0 is `agent/getAuthenticatedExtendedCard`. https://a2a-protocol.org/v0.3.0/specification/#710-agentgetauthenticatedextendedcard
1 parent 418a433 commit 5d22186

4 files changed

Lines changed: 76 additions & 12 deletions

File tree

src/a2a/compat/v0_3/jsonrpc_adapter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class JSONRPC03Adapter:
5959
'tasks/pushNotificationConfig/list': types_v03.ListTaskPushNotificationConfigRequest,
6060
'tasks/pushNotificationConfig/delete': types_v03.DeleteTaskPushNotificationConfigRequest,
6161
'tasks/resubscribe': types_v03.TaskResubscriptionRequest,
62-
'agent/authenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest,
62+
'agent/getAuthenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest,
6363
}
6464

6565
def __init__( # noqa: PLR0913
@@ -225,7 +225,7 @@ async def _process_non_streaming_request(
225225
id=request_id, result=None
226226
)
227227
)
228-
elif method == 'agent/authenticatedExtendedCard':
228+
elif method == 'agent/getAuthenticatedExtendedCard':
229229
res_card = await self.get_authenticated_extended_card(
230230
request_obj, context
231231
)
@@ -248,7 +248,7 @@ async def get_authenticated_extended_card(
248248
request: types_v03.GetAuthenticatedExtendedCardRequest,
249249
context: ServerCallContext,
250250
) -> types_v03.AgentCard:
251-
"""Handles the 'agent/authenticatedExtendedCard' JSON-RPC method."""
251+
"""Handles the 'agent/getAuthenticatedExtendedCard' JSON-RPC method."""
252252
if not self.agent_card.capabilities.extended_agent_card:
253253
raise ExtendedAgentCardNotConfiguredError(
254254
message='Authenticated card not supported'

src/a2a/compat/v0_3/jsonrpc_transport.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ async def get_extended_agent_card(
376376
return card
377377

378378
rpc_request = JSONRPC20Request(
379-
method='agent/authenticatedExtendedCard',
379+
method='agent/getAuthenticatedExtendedCard',
380380
params={},
381381
_id=str(uuid4()),
382382
)

tests/compat/v0_3/test_jsonrpc_app_compat.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111
from a2a.server.request_handlers.request_handler import RequestHandler
1212
from a2a.types.a2a_pb2 import (
1313
AgentCard,
14+
AgentCapabilities,
15+
AgentInterface,
1416
Message as Message10,
1517
Part as Part10,
1618
Role as Role10,
1719
Task as Task10,
1820
TaskStatus as TaskStatus10,
1921
TaskState as TaskState10,
2022
)
23+
2124
from a2a.compat.v0_3 import a2a_v0_3_pb2
2225

2326

@@ -44,15 +47,21 @@ def mock_handler():
4447

4548
@pytest.fixture
4649
def test_app(mock_handler):
47-
mock_agent_card = MagicMock(spec=AgentCard)
48-
mock_agent_card.url = 'http://mockurl.com'
49-
# Set up capabilities.streaming to avoid validation issues
50-
mock_agent_card.capabilities = MagicMock()
51-
mock_agent_card.capabilities.streaming = False
52-
mock_agent_card.capabilities.push_notifications = True
53-
mock_agent_card.capabilities.extended_agent_card = True
50+
agent_card = AgentCard(
51+
name='TestAgent',
52+
description='Test Description',
53+
version='1.0.0',
54+
capabilities=AgentCapabilities(
55+
streaming=False, push_notifications=True, extended_agent_card=True
56+
),
57+
)
58+
interface = agent_card.supported_interfaces.add()
59+
interface.url = 'http://mockurl.com'
60+
interface.protocol_binding = 'jsonrpc'
61+
interface.protocol_version = '0.3'
62+
5463
jsonrpc_routes = create_jsonrpc_routes(
55-
agent_card=mock_agent_card,
64+
agent_card=agent_card,
5665
request_handler=mock_handler,
5766
enable_v0_3_compat=True,
5867
rpc_url='/',
@@ -111,3 +120,25 @@ def test_get_task_v03_compat(
111120
assert 'result' in data
112121
assert data['result']['id'] == 'test_task_id'
113122
assert data['result']['status']['state'] == 'completed'
123+
124+
125+
def test_get_extended_agent_card_v03_compat(
126+
client: TestClient,
127+
) -> None:
128+
"""Test that the v0.3 method name 'agent/getAuthenticatedExtendedCard' is correctly routed."""
129+
request_payload = {
130+
'jsonrpc': '2.0',
131+
'id': '3',
132+
'method': 'agent/getAuthenticatedExtendedCard',
133+
'params': {},
134+
}
135+
136+
response = client.post('/', json=request_payload)
137+
assert response.status_code == 200
138+
data = response.json()
139+
140+
assert data['jsonrpc'] == '2.0'
141+
assert data['id'] == '3'
142+
assert 'result' in data
143+
# The result should be a v0.3 AgentCard
144+
assert 'supportsAuthenticatedExtendedCard' in data['result']

tests/compat/v0_3/test_jsonrpc_transport.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,39 @@ async def test_compat_jsonrpc_transport_get_extended_agent_card_not_supported(
348348
assert response == transport.agent_card
349349

350350

351+
@pytest.mark.asyncio
352+
async def test_compat_jsonrpc_transport_get_extended_agent_card_method_name(
353+
transport,
354+
):
355+
"""Verify the correct v0.3 method name 'agent/getAuthenticatedExtendedCard' is used."""
356+
captured_request: dict | None = None
357+
358+
async def mock_send_request(data, *args, **kwargs):
359+
nonlocal captured_request
360+
captured_request = data
361+
return {
362+
'result': {
363+
'name': 'ExtendedAgent',
364+
'url': 'http://agent',
365+
'version': '1.0.0',
366+
'description': 'Description',
367+
'skills': [],
368+
'defaultInputModes': [],
369+
'defaultOutputModes': [],
370+
'capabilities': {},
371+
'supportsAuthenticatedExtendedCard': True,
372+
}
373+
}
374+
375+
transport._send_request = mock_send_request
376+
377+
req = GetExtendedAgentCardRequest()
378+
await transport.get_extended_agent_card(req)
379+
380+
assert captured_request is not None
381+
assert captured_request['method'] == 'agent/getAuthenticatedExtendedCard'
382+
383+
351384
@pytest.mark.asyncio
352385
async def test_compat_jsonrpc_transport_close(transport, mock_httpx_client):
353386
await transport.close()

0 commit comments

Comments
 (0)