chore: Add support for authenticated extended card method (#356) · a2aproject/a2a-python@b567e80 · GitHub
Skip to content

Commit b567e80

Browse files
authored
chore: Add support for authenticated extended card method (#356)
# Description Types are manually generated for implementing this PR, but this feature has types dependency on a2aproject/A2A#929 and can only be merged once the type changes are merged into this repository. This PR adds support for agent/authenticatedExtendedCard JSON-RPC method for serving authenticated extended card. The previous HTTP GET /agent/authenticatedExtendedCard endpoint has been deprecated and will be removed in a future release. Release-As: 0.3.0
1 parent 83304bb commit b567e80

5 files changed

Lines changed: 122 additions & 1 deletion

File tree

‎src/a2a/server/apps/jsonrpc/fastapi_app.py‎

Lines changed: 1 addition & 0 deletions

‎src/a2a/server/apps/jsonrpc/jsonrpc_app.py‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@
3232
AgentCard,
3333
CancelTaskRequest,
3434
DeleteTaskPushNotificationConfigRequest,
35+
GetAuthenticatedExtendedCardRequest,
3536
GetTaskPushNotificationConfigRequest,
3637
GetTaskRequest,
3738
InternalError,
3839
InvalidRequestError,
3940
JSONParseError,
4041
JSONRPCError,
4142
JSONRPCErrorResponse,
43+
JSONRPCRequest,
4244
JSONRPCResponse,
4345
ListTaskPushNotificationConfigRequest,
4446
SendMessageRequest,
@@ -143,7 +145,9 @@ def __init__(
143145
self.agent_card = agent_card
144146
self.extended_agent_card = extended_agent_card
145147
self.handler = JSONRPCHandler(
146-
agent_card=agent_card, request_handler=http_handler
148+
agent_card=agent_card,
149+
request_handler=http_handler,
150+
extended_agent_card=extended_agent_card,
147151
)
148152
if (
149153
self.agent_card.supports_authenticated_extended_card
@@ -213,7 +217,16 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911
213217

214218
try:
215219
body = await request.json()
220+
if isinstance(body, dict):
221+
request_id = body.get('id')
222+
223+
# First, validate the basic JSON-RPC structure. This is crucial
224+
# because the A2ARequest model is a discriminated union where some
225+
# request types have default values for the 'method' field
226+
JSONRPCRequest.model_validate(body)
227+
216228
a2a_request = A2ARequest.model_validate(body)
229+
217230
call_context = self._context_builder.build(request)
218231

219232
request_id = a2a_request.root.id
@@ -353,6 +366,13 @@ async def _process_non_streaming_request(
353366
context,
354367
)
355368
)
369+
case GetAuthenticatedExtendedCardRequest():
370+
handler_result = (
371+
await self.handler.get_authenticated_extended_card(
372+
request_obj,
373+
context,
374+
)
375+
)
356376
case _:
357377
logger.error(
358378
f'Unhandled validated request type: {type(request_obj)}'
@@ -450,6 +470,10 @@ async def _handle_get_authenticated_extended_agent_card(
450470
self, request: Request
451471
) -> JSONResponse:
452472
"""Handles GET requests for the authenticated extended agent card."""
473+
logger.warning(
474+
'HTTP GET for authenticated extended card has been called by a client. '
475+
'This endpoint is deprecated in favor of agent/authenticatedExtendedCard JSON-RPC method and will be removed in a future release.'
476+
)
453477
if not self.agent_card.supports_authenticated_extended_card:
454478
return JSONResponse(
455479
{'error': 'Extended agent card not supported or not enabled.'},

‎src/a2a/server/apps/jsonrpc/starlette_app.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def routes(
9898
)
9999
)
100100

101+
# TODO: deprecated endpoint to be removed in a future release
101102
if self.agent_card.supports_authenticated_extended_card:
102103
app_routes.append(
103104
Route(

‎src/a2a/server/request_handlers/jsonrpc_handler.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77
from a2a.server.request_handlers.response_helpers import prepare_response_object
88
from a2a.types import (
99
AgentCard,
10+
AuthenticatedExtendedCardNotConfiguredError,
1011
CancelTaskRequest,
1112
CancelTaskResponse,
1213
CancelTaskSuccessResponse,
1314
DeleteTaskPushNotificationConfigRequest,
1415
DeleteTaskPushNotificationConfigResponse,
1516
DeleteTaskPushNotificationConfigSuccessResponse,
17+
GetAuthenticatedExtendedCardRequest,
18+
GetAuthenticatedExtendedCardResponse,
19+
GetAuthenticatedExtendedCardSuccessResponse,
1620
GetTaskPushNotificationConfigRequest,
1721
GetTaskPushNotificationConfigResponse,
1822
GetTaskPushNotificationConfigSuccessResponse,
@@ -57,15 +61,18 @@ def __init__(
5761
self,
5862
agent_card: AgentCard,
5963
request_handler: RequestHandler,
64+
extended_agent_card: AgentCard | None = None,
6065
):
6166
"""Initializes the JSONRPCHandler.
6267
6368
Args:
6469
agent_card: The AgentCard describing the agent's capabilities.
6570
request_handler: The underlying `RequestHandler` instance to delegate requests to.
71+
extended_agent_card: An optional, distinct Extended AgentCard to be served
6672
"""
6773
self.agent_card = agent_card
6874
self.request_handler = request_handler
75+
self.extended_agent_card = extended_agent_card
6976

7077
async def on_message_send(
7178
self,
@@ -395,3 +402,31 @@ async def delete_push_notification_config(
395402
id=request.id, error=e.error if e.error else InternalError()
396403
)
397404
)
405+
406+
async def get_authenticated_extended_card(
407+
self,
408+
request: GetAuthenticatedExtendedCardRequest,
409+
context: ServerCallContext | None = None,
410+
) -> GetAuthenticatedExtendedCardResponse:
411+
"""Handles the 'agent/authenticatedExtendedCard' JSON-RPC method.
412+
413+
Args:
414+
request: The incoming `GetAuthenticatedExtendedCardRequest` object.
415+
context: Context provided by the server.
416+
417+
Returns:
418+
A `GetAuthenticatedExtendedCardResponse` object containing the config or a JSON-RPC error.
419+
"""
420+
if self.extended_agent_card is None:
421+
return GetAuthenticatedExtendedCardResponse(
422+
root=JSONRPCErrorResponse(
423+
id=request.id,
424+
error=AuthenticatedExtendedCardNotConfiguredError(),
425+
)
426+
)
427+
428+
return GetAuthenticatedExtendedCardResponse(
429+
root=GetAuthenticatedExtendedCardSuccessResponse(
430+
id=request.id, result=self.extended_agent_card
431+
)
432+
)

‎tests/server/request_handlers/test_jsonrpc_handler.py‎

Lines changed: 60 additions & 0 deletions

0 commit comments

Comments
 (0)