11import json
22import logging
33import traceback
4-
54from collections .abc import AsyncGenerator
65from typing import Any
76
3837)
3938from a2a .utils .errors import MethodNotImplementedError
4039
41-
4240logger = logging .getLogger (__name__ )
4341
4442
@@ -247,25 +245,74 @@ async def event_generator(
247245
248246 async def _handle_get_agent_card (self , request : Request ) -> JSONResponse :
249247 """Handles GET requests for the agent card."""
248+ # Construct the public view of the agent card.
249+ public_card_data = {
250+ "version" : self .agent_card .version ,
251+ "name" : self .agent_card .name ,
252+ "providerName" : self .agent_card .provider .organization if self .agent_card .provider else None ,
253+ "url" : self .agent_card .url ,
254+ "authentication" : self .agent_card .authentication .model_dump (mode = 'json' , exclude_none = True )
255+ if self .agent_card .authentication else None , # authentication is a single object, can be None if made Optional
256+ "skills" : [
257+ f .model_dump (mode = 'json' , exclude_none = True )
258+ for f in self .agent_card .skills if f .id == 'hello_world' # Explicitly filter for public skills
259+ ]
260+ if self .agent_card .skills
261+ else [], # Default to empty list if no skills
262+ "capabilities" : self .agent_card .capabilities .model_dump (
263+ mode = 'json' , exclude_none = True
264+ ),
265+ "supportsAuthenticatedExtendedCard" : (
266+ self .agent_card .supportsAuthenticatedExtendedCard
267+ ),
268+ # Include other fields from types.py AgentCard designated as public
269+ "description" : self .agent_card .description ,
270+ "documentationUrl" : self .agent_card .documentationUrl ,
271+ "defaultInputModes" : self .agent_card .defaultInputModes ,
272+ "defaultOutputModes" : self .agent_card .defaultOutputModes ,
273+ }
274+ # Filter out None values from the public card data.
275+ public_card_data_cleaned = {
276+ k : v for k , v in public_card_data .items () if v is not None
277+ }
278+ return JSONResponse (public_card_data_cleaned )
279+
280+ async def _handle_get_authenticated_extended_agent_card (
281+ self , request : Request
282+ ) -> JSONResponse :
283+ """Handles GET requests for the authenticated extended agent card."""
284+ if not self .agent_card .supportsAuthenticatedExtendedCard :
285+ return JSONResponse (
286+ {"error" : "Extended agent card not supported or not enabled." },
287+ status_code = 404 ,
288+ )
289+
290+ # Authentication and authorization are NOT YET IMPLEMENTED for this endpoint.
291+ # As per current requirements, if 'supportsAuthenticatedExtendedCard' is true,
292+ # this endpoint returns the complete agent card.
293+ # In the future, proper authentication checks will be added here, and the
294+ # returned card may be filtered based on the client's authorization scopes.
250295 return JSONResponse (
251296 self .agent_card .model_dump (mode = 'json' , exclude_none = True )
252297 )
253298
254299 def routes (
255300 self ,
256301 agent_card_url : str = '/.well-known/agent.json' ,
302+ extended_agent_card_url : str = '/agent/authenticatedExtendedCard' ,
257303 rpc_url : str = '/' ,
258304 ) -> list [Route ]:
259305 """Returns the Starlette Routes for handling A2A requests.
260306
261307 Args:
262308 agent_card_url: The URL for the agent card endpoint.
263309 rpc_url: The URL for the A2A JSON-RPC endpoint
310+ extended_agent_card_url: The URL for the authenticated extended agent card endpoint.
264311
265312 Returns:
266313 The Starlette Routes serving A2A requests.
267314 """
268- return [
315+ app_routes = [
269316 Route (
270317 rpc_url ,
271318 self ._handle_requests ,
@@ -280,9 +327,21 @@ def routes(
280327 ),
281328 ]
282329
330+ if self .agent_card .supportsAuthenticatedExtendedCard :
331+ app_routes .append (
332+ Route (
333+ extended_agent_card_url ,
334+ self ._handle_get_authenticated_extended_agent_card ,
335+ methods = ['GET' ],
336+ name = 'authenticated_extended_agent_card' ,
337+ )
338+ )
339+ return app_routes
340+
283341 def build (
284342 self ,
285343 agent_card_url : str = '/.well-known/agent.json' ,
344+ extended_agent_card_url : str = '/agent/authenticatedExtendedCard' ,
286345 rpc_url : str = '/' ,
287346 ** kwargs : Any ,
288347 ) -> Starlette :
@@ -291,16 +350,17 @@ def build(
291350 Args:
292351 agent_card_url: The URL for the agent card endpoint.
293352 rpc_url: The URL for the A2A JSON-RPC endpoint
353+ extended_agent_card_url: The URL for the authenticated extended agent card endpoint.
294354 **kwargs: Additional keyword arguments to pass to the Starlette
295355 constructor.
296356
297357 Returns:
298358 A configured Starlette application instance.
299359 """
300- routes = self .routes (agent_card_url , rpc_url )
360+ app_routes = self .routes (agent_card_url , extended_agent_card_url , rpc_url )
301361 if 'routes' in kwargs :
302- kwargs ['routes' ] += routes
362+ kwargs ['routes' ]. extend ( app_routes )
303363 else :
304- kwargs ['routes' ] = routes
364+ kwargs ['routes' ] = app_routes
305365
306366 return Starlette (** kwargs )
0 commit comments