1+ import contextlib
12import json
23import logging
34import traceback
5+
46from abc import ABC , abstractmethod
57from collections .abc import AsyncGenerator
68from typing import Any
79
810from pydantic import ValidationError
911from sse_starlette .sse import EventSourceResponse
1012from starlette .applications import Starlette
13+ from starlette .authentication import BaseUser
1114from starlette .requests import Request
1215from starlette .responses import JSONResponse , Response
1316from starlette .routing import Route
1417
18+ from a2a .auth .user import User as A2AUser
1519from a2a .server .context import ServerCallContext
1620from a2a .server .request_handlers .jsonrpc_handler import JSONRPCHandler
1721from a2a .server .request_handlers .request_handler import RequestHandler
18- from a2a .types import (A2AError , A2ARequest , AgentCard , CancelTaskRequest ,
19- GetTaskPushNotificationConfigRequest , GetTaskRequest ,
20- InternalError , InvalidRequestError , JSONParseError ,
21- JSONRPCError , JSONRPCErrorResponse , JSONRPCResponse ,
22- SendMessageRequest , SendStreamingMessageRequest ,
23- SendStreamingMessageResponse ,
24- SetTaskPushNotificationConfigRequest ,
25- TaskResubscriptionRequest , UnsupportedOperationError )
22+ from a2a .types import (
23+ A2AError ,
24+ A2ARequest ,
25+ AgentCard ,
26+ CancelTaskRequest ,
27+ GetTaskPushNotificationConfigRequest ,
28+ GetTaskRequest ,
29+ InternalError ,
30+ InvalidRequestError ,
31+ JSONParseError ,
32+ JSONRPCError ,
33+ JSONRPCErrorResponse ,
34+ JSONRPCResponse ,
35+ SendMessageRequest ,
36+ SendStreamingMessageRequest ,
37+ SendStreamingMessageResponse ,
38+ SetTaskPushNotificationConfigRequest ,
39+ TaskResubscriptionRequest ,
40+ UnsupportedOperationError ,
41+ )
2642from a2a .utils .errors import MethodNotImplementedError
2743
44+
2845logger = logging .getLogger (__name__ )
2946
47+ # Register Starlette User as an implementation of a2a.auth.user.User
48+ A2AUser .register (BaseUser )
49+
3050
3151class CallContextBuilder (ABC ):
3252 """A class for building ServerCallContexts using the Starlette Request."""
@@ -36,6 +56,18 @@ def build(self, request: Request) -> ServerCallContext:
3656 """Builds a ServerCallContext from a Starlette Request."""
3757
3858
59+ class DefaultCallContextBuilder (CallContextBuilder ):
60+ """A default implementation of CallContextBuilder."""
61+
62+ def build (self , request : Request ) -> ServerCallContext :
63+ user = None
64+ state = {}
65+ with contextlib .suppress (Exception ):
66+ user = request .user
67+ state ['auth' ] = request .auth
68+ return ServerCallContext (user = user , state = state )
69+
70+
3971class A2AStarletteApplication :
4072 """A Starlette application implementing the A2A protocol server endpoints.
4173
@@ -75,7 +107,7 @@ def __init__(
75107 logger .error (
76108 'AgentCard.supportsAuthenticatedExtendedCard is True, but no extended_agent_card was provided. The /agent/authenticatedExtendedCard endpoint will return 404.'
77109 )
78- self ._context_builder = context_builder
110+ self ._context_builder = context_builder or DefaultCallContextBuilder ()
79111
80112 def _generate_error_response (
81113 self , request_id : str | int | None , error : JSONRPCError | A2AError
@@ -137,11 +169,7 @@ async def _handle_requests(self, request: Request) -> Response:
137169 try :
138170 body = await request .json ()
139171 a2a_request = A2ARequest .model_validate (body )
140- call_context = (
141- self ._context_builder .build (request )
142- if self ._context_builder
143- else None
144- )
172+ call_context = self ._context_builder .build (request )
145173
146174 request_id = a2a_request .root .id
147175 request_obj = a2a_request .root
@@ -344,7 +372,9 @@ async def _handle_get_authenticated_extended_agent_card(
344372 # extended_agent_card was provided during server initialization,
345373 # return a 404
346374 return JSONResponse (
347- {'error' : 'Authenticated extended agent card is supported but not configured on the server.' },
375+ {
376+ 'error' : 'Authenticated extended agent card is supported but not configured on the server.'
377+ },
348378 status_code = 404 ,
349379 )
350380
0 commit comments