111111
112112
113113try :
114- from a2a .types import (
115- AgentCard ,
116- TransportProtocol ,
117- Message ,
118- TaskIdParams ,
119- TaskQueryParams ,
120- )
114+ from a2a .types import AgentCard
121115 from a2a .client import ClientConfig , ClientFactory
122-
123- AgentCard = AgentCard
124- TransportProtocol = TransportProtocol
125- Message = Message
126- ClientConfig = ClientConfig
127- ClientFactory = ClientFactory
128- TaskIdParams = TaskIdParams
129- TaskQueryParams = TaskQueryParams
116+ from a2a .utils .constants import TransportProtocol
130117except (ImportError , AttributeError ):
131118 AgentCard = None
132119 TransportProtocol = None
133- Message = None
134120 ClientConfig = None
135121 ClientFactory = None
136- TaskIdParams = None
137- TaskQueryParams = None
122+ SendMessageRequest = None
123+ GetTaskRequest = None
124+ CancelTaskRequest = None
125+ GetExtendedAgentCardRequest = None
138126try :
139127 from autogen .agentchat import chat
140128
@@ -1807,79 +1795,53 @@ def _wrap_a2a_operation(method_name: str, agent_card: str) -> Callable[..., list
18071795 Args:
18081796 method_name: The name of the Agent Engine method to call.
18091797 agent_card: The agent card to use for the A2A API call.
1810- Example:
1811- {'additionalInterfaces': None,
1812- 'capabilities': {'extensions': None,
1813- 'pushNotifications': None,
1814- 'stateTransitionHistory': None,
1815- 'streaming': False},
1816- 'defaultInputModes': ['text'],
1817- 'defaultOutputModes': ['text'],
1818- 'description': (
1819- 'A helpful assistant agent that can answer questions.'
1820- ),
1821- 'documentationUrl': None,
1822- 'iconUrl': None,
1823- 'name': 'Q&A Agent',
1824- 'preferredTransport': 'JSONRPC',
1825- 'protocolVersion': '0.3.0',
1826- 'provider': None,
1827- 'security': None,
1828- 'securitySchemes': None,
1829- 'signatures': None,
1830- 'skills': [{
1831- 'description': (
1832- 'A helpful assistant agent that can answer questions.'
1833- ),
1834- 'examples': ['Who is leading 2025 F1 Standings?',
1835- 'Where can i find an active volcano?'],
1836- 'id': 'question_answer',
1837- 'inputModes': None,
1838- 'name': 'Q&A Agent',
1839- 'outputModes': None,
1840- 'security': None,
1841- 'tags': ['Question-Answer']}],
1842- 'supportsAuthenticatedExtendedCard': True,
1843- 'url': 'http://localhost:8080/',
1844- 'version': '1.0.0'}
1798+ Example: { 'name': 'Sample Agent', 'description': ( 'A helpful
1799+ assistant agent that can answer questions.' ),
1800+ 'supportedInterfaces': [{ 'url': 'http://localhost:8080/a2a/rest/',
1801+ 'protocolBinding': 'HTTP+JSON', 'protocolVersion': '1.0', }],
1802+ 'version': '1.0.0', 'capabilities': { 'streaming': True,
1803+ 'pushNotifications': False, 'extendedAgentCard': True, },
1804+ 'defaultInputModes': ['text'], 'defaultOutputModes': ['text'],
1805+ 'skills': [{ 'id': 'question_answer', 'name': 'Q&A Agent',
1806+ 'description': ( 'A helpful assistant agent that can answer
1807+ questions.' ), 'tags': ['Question-Answer'], 'examples': [ 'Who is
1808+ leading 2025 F1 Standings?', 'Where can i find an active volcano?',
1809+ ], 'inputModes': ['text'], 'outputModes': ['text'], }], }
1810+
18451811 Returns:
18461812 A callable object that executes the method on the Agent Engine via
18471813 the A2A API.
18481814 """
18491815
18501816 async def _method (self , ** kwargs ) -> Any : # type: ignore[no-untyped-def]
1851- """Wraps an Agent Engine method, creating a callable for A2A API."""
18521817 if not self .api_client :
18531818 raise ValueError ("api_client is not initialized." )
18541819 if not self .api_resource :
18551820 raise ValueError ("api_resource is not initialized." )
1856- a2a_agent_card = AgentCard (** json .loads (agent_card ))
1857- # A2A + AE integration currently only supports Rest API.
1858- if (
1859- a2a_agent_card .preferred_transport
1860- and a2a_agent_card .preferred_transport != TransportProtocol .http_json
1861- ):
1862- raise ValueError (
1863- "Only HTTP+JSON is supported for preferred transport on agent card "
1864- )
18651821
1866- # Set preferred transport to HTTP+JSON if not set.
1867- if not hasattr (a2a_agent_card , "preferred_transport" ):
1868- a2a_agent_card .preferred_transport = TransportProtocol .http_json
1822+ a2a_agent_card = AgentCard ()
1823+ json_format .ParseDict (
1824+ json .loads (agent_card ), a2a_agent_card , ignore_unknown_fields = True
1825+ )
18691826
1870- if not hasattr (a2a_agent_card .capabilities , "streaming" ):
1871- a2a_agent_card .capabilities .streaming = False
1827+ if a2a_agent_card .supported_interfaces :
1828+ interface = a2a_agent_card .supported_interfaces [0 ]
1829+ if interface .protocol_binding != TransportProtocol .HTTP_JSON :
1830+ raise ValueError (
1831+ "Only HTTP+JSON is supported for preferred transport on agent card"
1832+ )
1833+ else :
1834+ raise ValueError ("Agent card does not define any supported interfaces." )
18721835
1873- # agent_card is set on the class_methods before set_up is invoked.
1874- # Ensure that the agent_card url is set correctly before the client is created.
18751836 base_url = self .api_client ._api_client ._http_options .base_url .rstrip ("/" )
18761837 api_version = self .api_client ._api_client ._http_options .api_version
1877- a2a_agent_card .url = f"{ base_url } /{ api_version } /{ self .api_resource .name } /a2a"
1838+ a2a_agent_card .supported_interfaces [0 ].url = (
1839+ f"{ base_url } /{ api_version } /{ self .api_resource .name } /a2a"
1840+ )
18781841
1879- # Using a2a client, inject the auth token from the global config.
18801842 config = ClientConfig (
1881- supported_transports = [
1882- TransportProtocol .http_json ,
1843+ supported_protocol_bindings = [
1844+ TransportProtocol .HTTP_JSON ,
18831845 ],
18841846 use_client_preference = True ,
18851847 httpx_client = httpx .AsyncClient (
@@ -1898,23 +1860,34 @@ async def _method(self, **kwargs) -> Any: # type: ignore[no-untyped-def]
18981860 factory = ClientFactory (config )
18991861 client = factory .create (a2a_agent_card )
19001862
1863+ context = kwargs .pop ("context" , None )
1864+ if context is not None :
1865+ from a2a .client .client import ClientCallContext
1866+
1867+ if not isinstance (context , ClientCallContext ):
1868+ actual_context = ClientCallContext ()
1869+ if hasattr (context , "state" ):
1870+ actual_context .state = context .state
1871+ elif isinstance (context , dict ):
1872+ actual_context .state = context
1873+ context = actual_context
1874+
1875+ req = kwargs ["request" ]
19011876 if method_name == "on_message_send" :
1902- response = client .send_message (Message ( ** kwargs ) )
1877+ response = client .send_message (req , context = context )
19031878 chunks = []
19041879 async for chunk in response :
19051880 chunks .append (chunk )
19061881 return chunks
19071882 elif method_name == "on_get_task" :
1908- response = await client .get_task (TaskQueryParams ( ** kwargs ) )
1883+ return await client .get_task (req , context = context )
19091884 elif method_name == "on_cancel_task" :
1910- response = await client .cancel_task (TaskIdParams ( ** kwargs ) )
1911- elif method_name == "handle_authenticated_agent_card " :
1912- response = await client .get_card ( )
1885+ return await client .cancel_task (req , context = context )
1886+ elif method_name == "on_get_extended_agent_card " :
1887+ return await client .get_extended_agent_card ( req , context = context )
19131888 else :
19141889 raise ValueError (f"Unknown method name: { method_name } " )
19151890
1916- return response
1917-
19181891 return _method # type: ignore[return-value]
19191892
19201893
0 commit comments