ag2 0.9.10__py3-none-any.whl → 0.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ag2 might be problematic. Click here for more details.

Files changed (42) hide show
  1. {ag2-0.9.10.dist-info → ag2-0.10.0.dist-info}/METADATA +14 -7
  2. {ag2-0.9.10.dist-info → ag2-0.10.0.dist-info}/RECORD +42 -24
  3. autogen/a2a/__init__.py +36 -0
  4. autogen/a2a/agent_executor.py +105 -0
  5. autogen/a2a/client.py +280 -0
  6. autogen/a2a/errors.py +18 -0
  7. autogen/a2a/httpx_client_factory.py +79 -0
  8. autogen/a2a/server.py +221 -0
  9. autogen/a2a/utils.py +165 -0
  10. autogen/agentchat/__init__.py +3 -0
  11. autogen/agentchat/agent.py +0 -2
  12. autogen/agentchat/chat.py +5 -1
  13. autogen/agentchat/contrib/llava_agent.py +1 -13
  14. autogen/agentchat/conversable_agent.py +178 -73
  15. autogen/agentchat/group/group_tool_executor.py +46 -15
  16. autogen/agentchat/group/guardrails.py +41 -33
  17. autogen/agentchat/group/multi_agent_chat.py +53 -0
  18. autogen/agentchat/group/safeguards/api.py +19 -2
  19. autogen/agentchat/group/safeguards/enforcer.py +134 -40
  20. autogen/agentchat/groupchat.py +45 -33
  21. autogen/agentchat/realtime/experimental/realtime_swarm.py +1 -3
  22. autogen/interop/pydantic_ai/pydantic_ai.py +1 -1
  23. autogen/llm_config/client.py +3 -2
  24. autogen/oai/bedrock.py +0 -13
  25. autogen/oai/client.py +15 -8
  26. autogen/oai/client_utils.py +30 -0
  27. autogen/oai/cohere.py +0 -10
  28. autogen/remote/__init__.py +18 -0
  29. autogen/remote/agent.py +199 -0
  30. autogen/remote/agent_service.py +142 -0
  31. autogen/remote/errors.py +17 -0
  32. autogen/remote/httpx_client_factory.py +131 -0
  33. autogen/remote/protocol.py +37 -0
  34. autogen/remote/retry.py +102 -0
  35. autogen/remote/runtime.py +96 -0
  36. autogen/testing/__init__.py +12 -0
  37. autogen/testing/messages.py +45 -0
  38. autogen/testing/test_agent.py +111 -0
  39. autogen/version.py +1 -1
  40. {ag2-0.9.10.dist-info → ag2-0.10.0.dist-info}/WHEEL +0 -0
  41. {ag2-0.9.10.dist-info → ag2-0.10.0.dist-info}/licenses/LICENSE +0 -0
  42. {ag2-0.9.10.dist-info → ag2-0.10.0.dist-info}/licenses/NOTICE.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ag2
3
- Version: 0.9.10
3
+ Version: 0.10.0
4
4
  Summary: A programming framework for agentic AI
5
5
  Project-URL: Homepage, https://ag2.ai/
6
6
  Project-URL: Documentation, https://docs.ag2.ai
@@ -28,7 +28,7 @@ Classifier: Topic :: Software Development
28
28
  Classifier: Topic :: Software Development :: Libraries
29
29
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
30
30
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
- Requires-Python: <3.14,>=3.10
31
+ Requires-Python: >=3.10
32
32
  Requires-Dist: anyio<5.0.0,>=3.0.0
33
33
  Requires-Dist: diskcache
34
34
  Requires-Dist: docker
@@ -38,6 +38,8 @@ Requires-Dist: pydantic<3,>=2.6.1
38
38
  Requires-Dist: python-dotenv
39
39
  Requires-Dist: termcolor
40
40
  Requires-Dist: tiktoken
41
+ Provides-Extra: a2a
42
+ Requires-Dist: a2a-sdk[http-server]<0.4,>=0.3.7; extra == 'a2a'
41
43
  Provides-Extra: anthropic
42
44
  Requires-Dist: anthropic[vertex]>=0.23.1; extra == 'anthropic'
43
45
  Provides-Extra: autobuild
@@ -72,11 +74,13 @@ Requires-Dist: crawl4ai<0.8,>=0.4.247; extra == 'crawl4ai'
72
74
  Provides-Extra: deepseek
73
75
  Requires-Dist: openai>=1.99.3; extra == 'deepseek'
74
76
  Provides-Extra: dev
77
+ Requires-Dist: a2a-sdk[http-server]<0.4,>=0.3.7; extra == 'dev'
75
78
  Requires-Dist: cairosvg; extra == 'dev'
76
79
  Requires-Dist: codespell==2.4.1; extra == 'dev'
77
80
  Requires-Dist: detect-secrets==1.5.0; extra == 'dev'
78
81
  Requires-Dist: dirty-equals==0.9.0; extra == 'dev'
79
82
  Requires-Dist: fastapi==0.116.1; extra == 'dev'
83
+ Requires-Dist: freezegun==1.5.5; extra == 'dev'
80
84
  Requires-Dist: ipykernel==6.30.1; extra == 'dev'
81
85
  Requires-Dist: jinja2==3.1.6; extra == 'dev'
82
86
  Requires-Dist: mcp>=1.11.0; extra == 'dev'
@@ -90,7 +94,6 @@ Requires-Dist: mkdocs-material==9.6.19; extra == 'dev'
90
94
  Requires-Dist: mkdocs-minify-plugin==0.8.0; extra == 'dev'
91
95
  Requires-Dist: mkdocs-redirects==1.2.2; extra == 'dev'
92
96
  Requires-Dist: mkdocstrings[python]==0.30.0; extra == 'dev'
93
- Requires-Dist: mock==5.2.0; extra == 'dev'
94
97
  Requires-Dist: mypy==1.17.1; extra == 'dev'
95
98
  Requires-Dist: nbclient==0.10.2; extra == 'dev'
96
99
  Requires-Dist: nbconvert==7.16.6; extra == 'dev'
@@ -117,6 +120,7 @@ Requires-Dist: types-requests; extra == 'dev'
117
120
  Requires-Dist: types-ujson; extra == 'dev'
118
121
  Requires-Dist: uv==0.8.15; extra == 'dev'
119
122
  Provides-Extra: docs
123
+ Requires-Dist: a2a-sdk[http-server]<0.4,>=0.3.7; extra == 'docs'
120
124
  Requires-Dist: cairosvg; extra == 'docs'
121
125
  Requires-Dist: jinja2==3.1.6; extra == 'docs'
122
126
  Requires-Dist: mcp>=1.11.0; extra == 'docs'
@@ -175,9 +179,10 @@ Provides-Extra: groq
175
179
  Requires-Dist: groq>=0.9.0; extra == 'groq'
176
180
  Provides-Extra: interop
177
181
  Requires-Dist: crewai[tools]<1,>=0.76; (python_version >= '3.10' and python_version < '3.13') and extra == 'interop'
182
+ Requires-Dist: fasta2a; extra == 'interop'
178
183
  Requires-Dist: langchain-community<1,>=0.3.12; extra == 'interop'
179
184
  Requires-Dist: litellm<=1.76.3; extra == 'interop'
180
- Requires-Dist: pydantic-ai==1.0.1; extra == 'interop'
185
+ Requires-Dist: pydantic-ai>=1.0.12; extra == 'interop'
181
186
  Requires-Dist: weaviate-client<5,>=4; (python_version >= '3.10' and python_version < '3.13') and extra == 'interop'
182
187
  Provides-Extra: interop-crewai
183
188
  Requires-Dist: crewai[tools]<1,>=0.76; (python_version >= '3.10' and python_version < '3.13') and extra == 'interop-crewai'
@@ -186,7 +191,8 @@ Requires-Dist: weaviate-client<5,>=4; (python_version >= '3.10' and python_versi
186
191
  Provides-Extra: interop-langchain
187
192
  Requires-Dist: langchain-community<1,>=0.3.12; extra == 'interop-langchain'
188
193
  Provides-Extra: interop-pydantic-ai
189
- Requires-Dist: pydantic-ai==1.0.1; extra == 'interop-pydantic-ai'
194
+ Requires-Dist: fasta2a; extra == 'interop-pydantic-ai'
195
+ Requires-Dist: pydantic-ai>=1.0.12; extra == 'interop-pydantic-ai'
190
196
  Provides-Extra: jupyter-executor
191
197
  Requires-Dist: ipykernel>=6.29.0; extra == 'jupyter-executor'
192
198
  Requires-Dist: jupyter-client>=8.6.0; extra == 'jupyter-executor'
@@ -301,9 +307,9 @@ Requires-Dist: chromadb; extra == 'teachable'
301
307
  Provides-Extra: test
302
308
  Requires-Dist: dirty-equals==0.9.0; extra == 'test'
303
309
  Requires-Dist: fastapi==0.116.1; extra == 'test'
310
+ Requires-Dist: freezegun==1.5.5; extra == 'test'
304
311
  Requires-Dist: ipykernel==6.30.1; extra == 'test'
305
312
  Requires-Dist: mcp>=1.11.0; extra == 'test'
306
- Requires-Dist: mock==5.2.0; extra == 'test'
307
313
  Requires-Dist: nbconvert==7.16.6; extra == 'test'
308
314
  Requires-Dist: nbformat==5.10.4; extra == 'test'
309
315
  Requires-Dist: pandas==2.3.2; extra == 'test'
@@ -317,11 +323,12 @@ Requires-Dist: fastapi<1,>=0.115.0; extra == 'twilio'
317
323
  Requires-Dist: twilio>=9.3.2; extra == 'twilio'
318
324
  Requires-Dist: uvicorn<1,>=0.30.6; extra == 'twilio'
319
325
  Provides-Extra: types
326
+ Requires-Dist: a2a-sdk[http-server]<0.4,>=0.3.7; extra == 'types'
320
327
  Requires-Dist: dirty-equals==0.9.0; extra == 'types'
321
328
  Requires-Dist: fastapi==0.116.1; extra == 'types'
329
+ Requires-Dist: freezegun==1.5.5; extra == 'types'
322
330
  Requires-Dist: ipykernel==6.30.1; extra == 'types'
323
331
  Requires-Dist: mcp>=1.11.0; extra == 'types'
324
- Requires-Dist: mock==5.2.0; extra == 'types'
325
332
  Requires-Dist: mypy==1.17.1; extra == 'types'
326
333
  Requires-Dist: nbconvert==7.16.6; extra == 'types'
327
334
  Requires-Dist: nbformat==5.10.4; extra == 'types'
@@ -13,19 +13,26 @@ autogen/retrieve_utils.py,sha256=omqOebRN95IJUrvukJR9e7wno4vB1m3sf_gHv4ormN0,200
13
13
  autogen/runtime_logging.py,sha256=PV4xLXLEscBWVcdGLecN1f8gZqpvqK0E2SH0Y5numUM,4701
14
14
  autogen/token_count_utils.py,sha256=k50Vii75GhjkiYuw0gaWd7PjtiR-ZucNcN0xSJkBRKo,10859
15
15
  autogen/types.py,sha256=-C23PYj5EdwPZxcL3r0wFLAsQTXyVReghsdKV5b9jO4,982
16
- autogen/version.py,sha256=2vfZBer6VxAqB4h1pmrGGjrOLwcvJdqlWSCJiJQeNAg,194
16
+ autogen/version.py,sha256=ygtxiiXGPJvnpNFQtZCKcrNxJ1Luy5BiYoB4BcfXIKg,194
17
17
  autogen/_website/__init__.py,sha256=c8B9TpO07x9neD0zsJWj6AaEdlcP-WvxrvVOGWLtamk,143
18
18
  autogen/_website/generate_api_references.py,sha256=cMzgnapuahybxmGHbddukJA3oZxj1uIktDdOyP4rGzU,14772
19
19
  autogen/_website/generate_mkdocs.py,sha256=z4mBUBF-EJH1JwLOL727ExclSFx_mVOleggSVpqyrEA,43170
20
20
  autogen/_website/notebook_processor.py,sha256=VK4bUWz0RvkbpxPN91Nit2h2h7SOamNqyjuKjif7P4M,16500
21
21
  autogen/_website/process_notebooks.py,sha256=3MW1oWdBh1id5OpFI_4SoJ2EEfmrNDD0xMkTC2Tcp8Y,25902
22
22
  autogen/_website/utils.py,sha256=5345c12pOXyEcLS1pciVJY4g7wDs_fGTAZ4HsDswGow,14704
23
- autogen/agentchat/__init__.py,sha256=d5jPpXeavynP9eh5uMIgJKbK3-3tywJBa6l3L9X4l34,1347
24
- autogen/agentchat/agent.py,sha256=HgKK4lGxu5sqITMpq3GC4EnrVN_1IqXcKKXY4fxYH6o,5769
23
+ autogen/a2a/__init__.py,sha256=F_1b_seEOxZ1XI5TS4-dDp8KpBWaCJMfAyuYt6hO9Ac,1031
24
+ autogen/a2a/agent_executor.py,sha256=jE1wsshCHP8mzcp3ufUD76Wy5fP-UwBYB0QLDIDrvEQ,3813
25
+ autogen/a2a/client.py,sha256=bxfi_34Lsdnkhn311PqVXJVzMa6yRVB_-KulwD8wLLI,11036
26
+ autogen/a2a/errors.py,sha256=ydsDYnjjZLSGqVIlNITEFLPoWV-Ctffl1w7e3-r0WQc,446
27
+ autogen/a2a/httpx_client_factory.py,sha256=XuK_rNEw47uqATsK9T7prgtLFbThL-nBbGzyPax3PkM,3213
28
+ autogen/a2a/server.py,sha256=Bd2z4nKOv5qMfbgaYcVCSojl--esA7l9_kuV922YCeU,8137
29
+ autogen/a2a/utils.py,sha256=c0v21fPOTMVQ9aVJc5JT3SKG69MWHyt3iRr3MS4llrc,4762
30
+ autogen/agentchat/__init__.py,sha256=LkVdKOYXz6LX-tzEpeCZHOSPlWtCkMT07XX8lKjf8OE,1439
31
+ autogen/agentchat/agent.py,sha256=M9XNAX6u20tL_oLrEWMxFXFaqWpaJVWHjpzWTfy7xpY,5723
25
32
  autogen/agentchat/assistant_agent.py,sha256=dP8gcG96BihPW34pvTlxMogRa0zONnQHwzxhQuQ2Jdg,5779
26
- autogen/agentchat/chat.py,sha256=dMDOy5irqZOGHQ4DQCMtN5cQKxk5xk-69sjaWDy7Y6w,14361
27
- autogen/agentchat/conversable_agent.py,sha256=n1pWoS85cyjoDIFo0cNpV-jynP7dzJDAtQEUPWW-YD8,197445
28
- autogen/agentchat/groupchat.py,sha256=ec7kvYXm0MYeXM-59YSu-WB-7hUfIMhD3FMYd17sJo0,90882
33
+ autogen/agentchat/chat.py,sha256=cdSb-SLJ0Mh_8QSx6zs9pM0jyND57p5DKjkynCpXxnE,14562
34
+ autogen/agentchat/conversable_agent.py,sha256=gyaALkmdDqcIz76kc5z27pahioGPdgh2GJ5lJyoGgts,200069
35
+ autogen/agentchat/groupchat.py,sha256=eHb4SJSq7gTkXt5ggW622Rayz556Fda2h_AYXTuMA54,91915
29
36
  autogen/agentchat/user_proxy_agent.py,sha256=cFxJiRryh-648X07tJrItibdbHwBuFEQ2Yox1hLgDt4,7585
30
37
  autogen/agentchat/utils.py,sha256=eWLFoB2qQBUW44PQiWJ5SRxT1w1UXxwL28JsjOwGqg0,8206
31
38
  autogen/agentchat/contrib/__init__.py,sha256=tOTe4nwbKj7elHpftAy3zS_embMDzncrKL98XKhY6-c,168
@@ -33,7 +40,7 @@ autogen/agentchat/contrib/agent_optimizer.py,sha256=TXNHD9-myPKXwurd_pjQ_rpRj0oh
33
40
  autogen/agentchat/contrib/gpt_assistant_agent.py,sha256=mms6DK0s91Y-iF_-GKY_WfWzLzz5hY2Q0TJOCYezNU0,24999
34
41
  autogen/agentchat/contrib/img_utils.py,sha256=NQ0yAbY5zugnl00ZVqBgNKyBYwiguEOFxtVTlSMQIfM,15115
35
42
  autogen/agentchat/contrib/llamaindex_conversable_agent.py,sha256=DD-JbrRnrsPKpLJPxtel7tS904giS1LTQmuFraDsCig,4533
36
- autogen/agentchat/contrib/llava_agent.py,sha256=AX0Kn1OPkpNzvYLlMuTWnvwvzhoZ2l7Yl2mRc84vUEE,7127
43
+ autogen/agentchat/contrib/llava_agent.py,sha256=9yTg1fUDu5lqi-58Im50buNmeXLQybPsfh5wZQeUf6M,6628
37
44
  autogen/agentchat/contrib/math_user_proxy_agent.py,sha256=Icw5nLbZwmzXsoGmFSE8KhTCknWOtJSkAdh78M9Wj8E,19678
38
45
  autogen/agentchat/contrib/multimodal_conversable_agent.py,sha256=zgFHgiaBitUJuJ3V6zGja42fyN4-otVceIK_Sx-1Ddg,5112
39
46
  autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py,sha256=WhKltVJkK_X7Y_eHTgXq4m9IthktVa3zgOt0vPOqV2U,19398
@@ -130,12 +137,12 @@ autogen/agentchat/group/context_condition.py,sha256=UwIOBqPzwi0emfkmseavTJJ6f0VA
130
137
  autogen/agentchat/group/context_expression.py,sha256=nzAVoI7RW0O1iuMyWpFZrVjGnHaQUsq8e83vXzzo06k,10012
131
138
  autogen/agentchat/group/context_str.py,sha256=Jv8v8oNFymZGmahWpARdBrXBkmZUZWBDsfMyKwzTtHw,1238
132
139
  autogen/agentchat/group/context_variables.py,sha256=1GkOokaaYX-Xc5b9ZylytjQxjhLAyY8MW3quPBJuoFM,5562
133
- autogen/agentchat/group/group_tool_executor.py,sha256=HNf9zhRGU2mBSlmyjhZDCy5Umyq2xMH4_hsMVSu5smQ,9110
140
+ autogen/agentchat/group/group_tool_executor.py,sha256=NkwKBO96wGhVz6aYrjtkqVXQFLcHMqUVdmxgkVpEvuQ,10692
134
141
  autogen/agentchat/group/group_utils.py,sha256=Y4KOZbqM81lqFmqg9K5xnbjr4YYBfk3iMkm1GK8tygs,27534
135
- autogen/agentchat/group/guardrails.py,sha256=WpCKT5j3q7317Dy_6wc-MQ_p58J4pTTXqtO5iyfLS7A,5920
142
+ autogen/agentchat/group/guardrails.py,sha256=F3aVn7ht-WCgz0uLC9f4Os8_yIEG0lgQ2XFrCi1GMKY,6324
136
143
  autogen/agentchat/group/handoffs.py,sha256=IOUCOtCFAfhITZhh01HK3ehRMdoBgmgU4gwlLn48ofQ,11633
137
144
  autogen/agentchat/group/llm_condition.py,sha256=wfuEET1VhyVVGedYxcyuhX_Vus6uZHxUl_SPpu4YIsc,2951
138
- autogen/agentchat/group/multi_agent_chat.py,sha256=lD7nM0fCTmhtcJrSTOeZcWds8zefXVsapdK3pMxySp8,7763
145
+ autogen/agentchat/group/multi_agent_chat.py,sha256=EdwDmLjRMsDrmHijDLVK5BK3Tg2t_FrZUsyjcvlF_Po,10289
139
146
  autogen/agentchat/group/on_condition.py,sha256=o7wVXlUQ2G5Z3Mbm_awWQlYnnG6x9_HcqSiY7Arw0NQ,2195
140
147
  autogen/agentchat/group/on_context_condition.py,sha256=Lh6m7kFt3dos1JLja3WPmH_9qTYhIkpM6hIL6T6YgU0,2032
141
148
  autogen/agentchat/group/reply_result.py,sha256=DItDGQdaUucCuOIw8kGQDpwt9Li80xvt6Phmo2_14Xk,705
@@ -147,8 +154,8 @@ autogen/agentchat/group/patterns/pattern.py,sha256=RMEPnMavpl7NP84hoaIZAwyQtxjHy
147
154
  autogen/agentchat/group/patterns/random.py,sha256=Zte7JVN9illCqNRi3MkOGqSvKtJXmPaefB5bbTgyScI,3347
148
155
  autogen/agentchat/group/patterns/round_robin.py,sha256=fYzkSoP7pi14Njvf5ZcKYBTymRglMo2BrB96HWzrC_o,3875
149
156
  autogen/agentchat/group/safeguards/__init__.py,sha256=FzXqb1WMhDdOlFDwL3RmkfIQ5kjjg885l2YSvwHXcws,668
150
- autogen/agentchat/group/safeguards/api.py,sha256=6yemSQkvgUUdlmitOcpFIC7EG6CwkPnlT8wCfYaRVmc,9017
151
- autogen/agentchat/group/safeguards/enforcer.py,sha256=FborG8oBURX0jmhX-fDq6h3QTppykXAtdyi9d8UO7c8,47821
157
+ autogen/agentchat/group/safeguards/api.py,sha256=zhbH3AqdK7nenvyWQpaVixBMjdlC9E6HdA8fmteBL9Q,9858
158
+ autogen/agentchat/group/safeguards/enforcer.py,sha256=UOSzH1T11VMM46ccq0-0wqRZvH7JfDXW49qAzhQMdhI,52661
152
159
  autogen/agentchat/group/safeguards/events.py,sha256=qHUo9Yi8gyPxtJIh6EmB8s_TQvUxl5a1UhVMezwZZZ0,4092
153
160
  autogen/agentchat/group/safeguards/validator.py,sha256=8B-i5VgKVfmCgmB0nhMLESM2DEC5hjOQUcjXlfTKyp4,22855
154
161
  autogen/agentchat/group/targets/__init__.py,sha256=AJNSbl9iMe2hiDmZojTp8h889o5OYN3V7f2_2nr8px4,145
@@ -163,7 +170,7 @@ autogen/agentchat/realtime/experimental/function_observer.py,sha256=WOA27ZfhvWMN
163
170
  autogen/agentchat/realtime/experimental/realtime_agent.py,sha256=HzNuAfIL5KxnqDa1ML2sLvHp_bS6UfzgRSgWxMEYzXg,5671
164
171
  autogen/agentchat/realtime/experimental/realtime_events.py,sha256=zmRr3pwPJpme5VZEADIz5vg9IZoT3Z1NAc3vt1RdWLk,1083
165
172
  autogen/agentchat/realtime/experimental/realtime_observer.py,sha256=Y_UULA9CgxqKZo9dgBds0iipjx7cZ9MghrH4HcKd57o,3045
166
- autogen/agentchat/realtime/experimental/realtime_swarm.py,sha256=zA2fbh34ftMyDH2AP-WfxLExaar0FFlLMki2gesmuEg,18056
173
+ autogen/agentchat/realtime/experimental/realtime_swarm.py,sha256=Bv_2WEReD84y2xnOUpxtiu0awLtcKyGqHoAysjFxQtA,18000
167
174
  autogen/agentchat/realtime/experimental/websockets.py,sha256=bj9b5eq80L3KlGWPP6nn7uyfT_Z47kQqtIRbQkeE5SI,667
168
175
  autogen/agentchat/realtime/experimental/audio_adapters/__init__.py,sha256=rd0pEy91LYq0JMvIk8Fv7ZKIQLK7oZbVdgVAwNZDCmQ,315
169
176
  autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py,sha256=jBr5I3j6Z2jF6J-PNTvvAW24L0NvJpCul4M_fVP4S-g,6091
@@ -270,7 +277,7 @@ autogen/interop/langchain/langchain_tool.py,sha256=KOlCvor9tQfx6BILC9O1Qmo4SS4XE
270
277
  autogen/interop/litellm/__init__.py,sha256=0K9NkQEBXKZI6UVNwD4daTumQL-uhMrAJE33wiSYmkI,237
271
278
  autogen/interop/litellm/litellm_config_factory.py,sha256=JuxNRMM4HwYebmOfs-jnH1Cf5uD3SM968pyVtW_49Cw,6272
272
279
  autogen/interop/pydantic_ai/__init__.py,sha256=w9tqh96x43Ipq2loD_F-kqwws2RFRs7-98mPxWG-Mjc,238
273
- autogen/interop/pydantic_ai/pydantic_ai.py,sha256=wYkm2cW4kCkiyB0fkJXWOOL1gD-kN1S4sNm6mdwnOTk,6704
280
+ autogen/interop/pydantic_ai/pydantic_ai.py,sha256=QZqxn9dqxtXxzyEe2NQxguMhgiqxv0MNdybn2oh2Ql4,6747
274
281
  autogen/io/__init__.py,sha256=c5iZkM24B9j3K0yPQ0HYJnvAdNMqhlRZVXqcfdnGFX4,600
275
282
  autogen/io/base.py,sha256=yBFUwpZxOFa4F5_dv4ZWoN8iiEy3oH6xgWoo-TK-bg0,4705
276
283
  autogen/io/console.py,sha256=6dYGWntAMgbVX2An14pcs5YyusFsUGeF_-tgR5IMOC0,1892
@@ -281,7 +288,7 @@ autogen/io/processors/__init__.py,sha256=8-znkWyHiESpMktD4cU_id-HPLE7JD7gArj0y-7
281
288
  autogen/io/processors/base.py,sha256=60oltHFRWIjZsxzzzK5evPx1M-H0lHZVNVkmItiTNSQ,685
282
289
  autogen/io/processors/console_event_processor.py,sha256=sdrVG8LmW2ZUMKoa8bhCpPz1NImz4dFcMaXj1VFlkYg,2214
283
290
  autogen/llm_config/__init__.py,sha256=P_jAlr_bz-xr8P0eLeUJ9aF7ruNW3bQ1b1d6lfaYP68,257
284
- autogen/llm_config/client.py,sha256=Ig5C2e9N37H9NutB0CThOViMUK99wFWfGw19lg_783k,2424
291
+ autogen/llm_config/client.py,sha256=3RANhMmES5du41qTigco-K2cFFf12Gmj-CGvfDP5Iwg,2488
285
292
  autogen/llm_config/config.py,sha256=A8N7Rf24cwXAWT-xr0K73IvrBCELyydkvX5gVKRKJAM,16725
286
293
  autogen/llm_config/entry.py,sha256=BaZ-o4ASeSN22BAwN9UgXQnJ_lXqLRylbn5vhZkr8YY,6190
287
294
  autogen/llm_config/types.py,sha256=alUNKdycgWPo524D0UzvYE25vqs5fjZaN0-z5znSl8w,1174
@@ -311,11 +318,11 @@ autogen/messages/client_messages.py,sha256=1OsKmdQSkt2gaAAz60Vf683oVJtLEkztLeowQ
311
318
  autogen/messages/print_message.py,sha256=XoAAOh08MiFBX82OLylweJSlba6Rj1DYfdHRmEMVDbs,1390
312
319
  autogen/oai/__init__.py,sha256=KcO_XkHR5B5P9jv5cLXsO1ybIiZ-fNvoagqn5CARonU,1741
313
320
  autogen/oai/anthropic.py,sha256=rstyTbGn9lSjpRUxNZWTwkx5qvjgRpf98PJg8CQgOuc,29230
314
- autogen/oai/bedrock.py,sha256=Og2Zq9NoaAl7pDKTLnrobXFZoFH8qlgMA2umx2CNyZw,26316
321
+ autogen/oai/bedrock.py,sha256=kNP5pMqqjeXmR7m-TBbyti1swDSbPO3owoTQDbdqTwY,25682
315
322
  autogen/oai/cerebras.py,sha256=emRF_2xy3gakapyEHYKvZEDvvALFR9AaBK9JeQpH1Tk,12350
316
- autogen/oai/client.py,sha256=8ISakc6RtqseNz64_MLES7P84K35x-ZMM6UbNIYj8I8,67184
317
- autogen/oai/client_utils.py,sha256=KZ0RKyYXcI84b9TxY1P_gzBSUySa7xJa2j-_zHObMtY,7519
318
- autogen/oai/cohere.py,sha256=Oil1OZsoOKaFGhFi7qGwxBgI5auyPfBsVpKbU6I3Gm8,20005
323
+ autogen/oai/client.py,sha256=xM0jNzhfcnTk1HYJ5IwwWdYYoro52V7DGdOPAktnCQk,67586
324
+ autogen/oai/client_utils.py,sha256=6nrrCsuDy8_JK1zbRCElhPujOiDMnEhLL7uVIa1F9Cc,8771
325
+ autogen/oai/cohere.py,sha256=VKmmQmAaCwcrcRCaljnoJBl1jQeo0P8VIMfOmjHcvFQ,19579
319
326
  autogen/oai/gemini.py,sha256=8XWEcqwFIH9lHv8xcMTuxEbcr-GLLEKeFO1mr4Pui88,43762
320
327
  autogen/oai/gemini_types.py,sha256=GGt0o1ozWdLobiZMzdtxmpDKKDW-bwgxOQkw5XvJPKI,5861
321
328
  autogen/oai/groq.py,sha256=J9YlpiYbKGOl5zsoInLdZfbFQqCUVXAAS666BRvkw48,12621
@@ -332,6 +339,17 @@ autogen/oai/oai_models/chat_completion_message.py,sha256=60C32Bj4UIGfCzO8CU8Vrtr
332
339
  autogen/oai/oai_models/chat_completion_message_tool_call.py,sha256=L0SzWLQq7MWW4hykArAuyZS_Tqz_AFuj18YKBQmYI_k,1771
333
340
  autogen/oai/oai_models/chat_completion_token_logprob.py,sha256=gC5o8BgScmAn9mBkCdWPgs4G6Es7xWp3spJC5aOxGCs,2031
334
341
  autogen/oai/oai_models/completion_usage.py,sha256=-37tfKln6QO-fwC4Smo_mxnjOiNrM_K1Ck26WHhvIP0,1968
342
+ autogen/remote/__init__.py,sha256=j39qEJIb3I4mCBYQ9ButvbSDcrh4-qJEuZWJkP8Z91c,511
343
+ autogen/remote/agent.py,sha256=Q2waHRtrEas-VsHmF-uYon2l5jlWf8-rYAX82FIB16c,7670
344
+ autogen/remote/agent_service.py,sha256=_urzWoxfTcdEvT5WjLvexKbdQrMCUGTA35Mf2zU_q8k,6278
345
+ autogen/remote/errors.py,sha256=e6qr7k-3mI8afCgnBtplZYsb5al1q6rYytwjVUTttvk,491
346
+ autogen/remote/httpx_client_factory.py,sha256=RbO3-d15ygiC744O4GLl-qX2uICqvsSUXXWWi8mGCrY,4822
347
+ autogen/remote/protocol.py,sha256=ILmcZtno9Com4BmtCBnKEPxFriI9EB4LEr5Fewh5kpw,1045
348
+ autogen/remote/retry.py,sha256=8RLm8ABbDE8ZQXO6wRndQxRDeIuNUnCkTaVLL8ag10U,2859
349
+ autogen/remote/runtime.py,sha256=nW4N_7RO2CS8gzP9fqAXuWhiU4q-8XuZE9e6SBJ00yk,3194
350
+ autogen/testing/__init__.py,sha256=e9yi2_Eplb5x59o-f-YR9RUd2sHukgCFHIK04BM7YZo,293
351
+ autogen/testing/messages.py,sha256=v9TaGiWkZclntSGAzbVK1LEC5nMHJrkPJUtcnLGVlIc,1513
352
+ autogen/testing/test_agent.py,sha256=i433We7sGIoqvJDX8o8dZ8GyoUSp7UdJwRiL836td7w,3671
335
353
  autogen/tools/__init__.py,sha256=guevGJut7uN2pGpPn9mODaVsTSfeHrGpjjjIEWRBqVo,554
336
354
  autogen/tools/dependency_injection.py,sha256=APcLOiajJkpjoicu3wUovjbb0pmidj4M8UUkdq5LsEE,8217
337
355
  autogen/tools/function_utils.py,sha256=n_C2H6Y0cG-oQw7YsTH6egQnFwRgEq0MLoe1Jt9vp4I,13762
@@ -388,8 +406,8 @@ autogen/tools/experimental/wikipedia/wikipedia.py,sha256=phtwNOW5KcvXq-1-3yYjm6E
388
406
  templates/main.jinja2,sha256=mu7z_4NjI1XMEwQx9KaFQixi4ImfwY0FZQaYUJVBnSc,1765
389
407
  templates/client_template/main.jinja2,sha256=9_1pmPNLlPZpfcE0KqXJ6uBVzQtmFqWbxs2xyzCOfxY,2115
390
408
  templates/config_template/config.jinja2,sha256=A-p-YBsnEm1iftBIhuIBfIyCY-qw34KWcxalmM6KPWc,167
391
- ag2-0.9.10.dist-info/METADATA,sha256=O1nmJ-5K3Vgvba9_O3MuuzIuevxCqY0ucyknXEGzwsg,35702
392
- ag2-0.9.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
393
- ag2-0.9.10.dist-info/licenses/LICENSE,sha256=GEFQVNayAR-S_rQD5l8hPdgvgyktVdy4Bx5-v90IfRI,11384
394
- ag2-0.9.10.dist-info/licenses/NOTICE.md,sha256=07iCPQGbth4pQrgkSgZinJGT5nXddkZ6_MGYcBd2oiY,1134
395
- ag2-0.9.10.dist-info/RECORD,,
409
+ ag2-0.10.0.dist-info/METADATA,sha256=NgS-U8xR1F_VGQI6u2-NPb9BRYe2B5WABpyKrFuBPXY,36090
410
+ ag2-0.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
411
+ ag2-0.10.0.dist-info/licenses/LICENSE,sha256=GEFQVNayAR-S_rQD5l8hPdgvgyktVdy4Bx5-v90IfRI,11384
412
+ ag2-0.10.0.dist-info/licenses/NOTICE.md,sha256=07iCPQGbth4pQrgkSgZinJGT5nXddkZ6_MGYcBd2oiY,1134
413
+ ag2-0.10.0.dist-info/RECORD,,
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ try:
5
+ from a2a.types import AgentCard
6
+ except ImportError as e:
7
+ raise ImportError("a2a-sdk is not installed. Please install it with:\npip install ag2[a2a]") from e
8
+
9
+ import warnings
10
+
11
+ warnings.warn(
12
+ (
13
+ "AG2 Implementation for A2A support is in experimental mode "
14
+ "and is subjected to breaking changes. Once it's stable enough the "
15
+ "experimental mode will be removed. Your feedback is welcome."
16
+ ),
17
+ ImportWarning,
18
+ stacklevel=2,
19
+ )
20
+
21
+ from autogen.remote.httpx_client_factory import HttpxClientFactory
22
+
23
+ from .agent_executor import AutogenAgentExecutor
24
+ from .client import A2aRemoteAgent
25
+ from .httpx_client_factory import MockClient
26
+ from .server import A2aAgentServer, CardSettings
27
+
28
+ __all__ = (
29
+ "A2aAgentServer",
30
+ "A2aRemoteAgent",
31
+ "AgentCard",
32
+ "AutogenAgentExecutor",
33
+ "CardSettings",
34
+ "HttpxClientFactory",
35
+ "MockClient",
36
+ )
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from datetime import datetime, timezone
6
+
7
+ from a2a.server.agent_execution import AgentExecutor, RequestContext
8
+ from a2a.server.events import EventQueue
9
+ from a2a.types import TaskArtifactUpdateEvent, TaskState, TaskStatus, TaskStatusUpdateEvent
10
+ from a2a.utils import new_task
11
+ from a2a.utils.message import new_agent_text_message
12
+
13
+ from autogen import ConversableAgent
14
+ from autogen.doc_utils import export_module
15
+ from autogen.remote.agent_service import AgentService
16
+
17
+ from .utils import request_message_from_a2a, response_message_to_a2a
18
+
19
+
20
+ @export_module("autogen.a2a")
21
+ class AutogenAgentExecutor(AgentExecutor):
22
+ """An agent executor that bridges Autogen ConversableAgents with A2A protocols.
23
+
24
+ This class wraps an Autogen ConversableAgent to enable it to be executed within
25
+ the A2A framework, handling message processing, task management, and event publishing.
26
+ """
27
+
28
+ def __init__(self, agent: ConversableAgent) -> None:
29
+ self.agent = AgentService(agent)
30
+
31
+ async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
32
+ assert context.message
33
+
34
+ task = context.current_task
35
+ if not task:
36
+ task = new_task(context.message)
37
+ task.status.timestamp = datetime.now(timezone.utc).isoformat()
38
+ # publish the task status submitted event
39
+ await event_queue.enqueue_event(task)
40
+
41
+ try:
42
+ result = await self.agent(request_message_from_a2a(context.message))
43
+
44
+ except Exception as e:
45
+ # publish the task status failed event
46
+ await event_queue.enqueue_event(
47
+ TaskStatusUpdateEvent(
48
+ task_id=task.id,
49
+ status=TaskStatus(
50
+ state=TaskState.failed,
51
+ message=new_agent_text_message(
52
+ str(e),
53
+ task_id=task.id,
54
+ context_id=context.context_id,
55
+ ),
56
+ timestamp=datetime.now(timezone.utc).isoformat(),
57
+ ),
58
+ context_id=context.context_id,
59
+ final=True,
60
+ )
61
+ )
62
+ return
63
+
64
+ artifact, messages = response_message_to_a2a(result, context.context_id, task.id)
65
+
66
+ # publish local chat history events
67
+ for message in messages:
68
+ await event_queue.enqueue_event(
69
+ TaskStatusUpdateEvent(
70
+ task_id=task.id,
71
+ status=TaskStatus(
72
+ state=TaskState.working,
73
+ message=message,
74
+ timestamp=datetime.now(timezone.utc).isoformat(),
75
+ ),
76
+ context_id=context.context_id,
77
+ final=False,
78
+ )
79
+ )
80
+
81
+ # publish the task result event
82
+ await event_queue.enqueue_event(
83
+ TaskArtifactUpdateEvent(
84
+ task_id=task.id,
85
+ last_chunk=True,
86
+ context_id=context.context_id,
87
+ artifact=artifact,
88
+ )
89
+ )
90
+
91
+ # publish the task status completed event
92
+ await event_queue.enqueue_event(
93
+ TaskStatusUpdateEvent(
94
+ task_id=task.id,
95
+ status=TaskStatus(
96
+ state=TaskState.completed,
97
+ timestamp=datetime.now(timezone.utc).isoformat(),
98
+ ),
99
+ context_id=context.context_id,
100
+ final=True,
101
+ )
102
+ )
103
+
104
+ async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
105
+ pass
autogen/a2a/client.py ADDED
@@ -0,0 +1,280 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import asyncio
6
+ import logging
7
+ from pprint import pformat
8
+ from typing import Any, cast
9
+ from uuid import uuid4
10
+
11
+ import httpx
12
+ from a2a.client import A2ACardResolver, A2AClientHTTPError, Client, ClientConfig, ClientEvent
13
+ from a2a.client import ClientFactory as A2AClientFactory
14
+ from a2a.types import AgentCard, Message, Task, TaskIdParams, TaskQueryParams, TaskState
15
+ from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH, EXTENDED_AGENT_CARD_PATH, PREV_AGENT_CARD_WELL_KNOWN_PATH
16
+
17
+ from autogen import ConversableAgent
18
+ from autogen.agentchat.group import ContextVariables
19
+ from autogen.doc_utils import export_module
20
+ from autogen.oai.client import OpenAIWrapper
21
+ from autogen.remote.httpx_client_factory import ClientFactory, EmptyClientFactory
22
+ from autogen.remote.protocol import RequestMessage, ResponseMessage
23
+
24
+ from .errors import A2aAgentNotFoundError, A2aClientError
25
+ from .utils import request_message_to_a2a, response_message_from_a2a_artifacts, response_message_from_a2a_message
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ @export_module("autogen.a2a")
31
+ class A2aRemoteAgent(ConversableAgent):
32
+ """`a2a-sdk`-based client for handling asynchronous communication with an A2A server.
33
+
34
+ It has fully-compatible with original `ConversableAgent` API, so you can easily integrate
35
+ remote A2A agents to existing collaborations.
36
+
37
+ Args:
38
+ url: The URL of the A2A server to connect to.
39
+ name: A unique identifier for this client instance.
40
+ silent: whether to print the message sent. If None, will use the value of silent in each function.
41
+ client: An optional HTTPX client instance factory.
42
+ client_config: A2A Client configuration options.
43
+ max_reconnects: Maximum number of reconnection attempts before giving up.
44
+ polling_interval: Time in seconds between polling operations. Works for A2A Servers doesn't support streaming.
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ url: str,
50
+ name: str,
51
+ *,
52
+ silent: bool | None = None,
53
+ client: ClientFactory | None = None,
54
+ client_config: ClientConfig | None = None,
55
+ max_reconnects: int = 3,
56
+ polling_interval: float = 0.5,
57
+ ) -> None:
58
+ self.url = url
59
+
60
+ self._httpx_client_factory = client or EmptyClientFactory()
61
+ self._max_reconnects = max_reconnects
62
+ self._polling_interval = polling_interval
63
+
64
+ super().__init__(name, silent=silent)
65
+
66
+ self.__llm_config: dict[str, Any] = {}
67
+
68
+ self._client_config = client_config or ClientConfig()
69
+ self.__agent_card: AgentCard | None = None
70
+
71
+ self.replace_reply_func(
72
+ ConversableAgent.generate_oai_reply,
73
+ A2aRemoteAgent.generate_remote_reply,
74
+ )
75
+ self.replace_reply_func(
76
+ ConversableAgent.a_generate_oai_reply,
77
+ A2aRemoteAgent.a_generate_remote_reply,
78
+ )
79
+
80
+ def generate_remote_reply(
81
+ self,
82
+ messages: list[dict[str, Any]] | None = None,
83
+ sender: ConversableAgent | None = None,
84
+ config: OpenAIWrapper | None = None,
85
+ ) -> tuple[bool, dict[str, Any] | None]:
86
+ raise NotImplementedError(f"{self.__class__.__name__} does not support synchronous reply generation")
87
+
88
+ async def a_generate_remote_reply(
89
+ self,
90
+ messages: list[dict[str, Any]] | None = None,
91
+ sender: ConversableAgent | None = None,
92
+ config: OpenAIWrapper | None = None,
93
+ ) -> tuple[bool, dict[str, Any] | None]:
94
+ if messages is None:
95
+ messages = self._oai_messages[sender]
96
+
97
+ if not self.__agent_card:
98
+ self.__agent_card = await self._get_agent_card()
99
+
100
+ initial_message = request_message_to_a2a(
101
+ request_message=RequestMessage(
102
+ messages=messages,
103
+ context=self.context_variables.data,
104
+ client_tools=self.__llm_config.get("tools", []),
105
+ ),
106
+ context_id=uuid4().hex,
107
+ )
108
+
109
+ self._client_config.httpx_client = self._httpx_client_factory()
110
+ async with self._client_config.httpx_client:
111
+ agent_client = A2AClientFactory(self._client_config).create(self.__agent_card)
112
+
113
+ if self.__agent_card.capabilities.streaming:
114
+ reply = await self._ask_streaming(agent_client, initial_message)
115
+ return self._apply_reply(reply, sender)
116
+
117
+ else:
118
+ reply = await self._ask_polling(agent_client, initial_message)
119
+ return self._apply_reply(reply, sender)
120
+
121
+ def _apply_reply(
122
+ self, reply: ResponseMessage | None, sender: ConversableAgent | None
123
+ ) -> tuple[bool, dict[str, Any] | None]:
124
+ if not reply:
125
+ return True, None
126
+
127
+ if sender and reply.context:
128
+ context_variables = ContextVariables(reply.context)
129
+ self.context_variables.update(context_variables.to_dict())
130
+ sender.context_variables.update(context_variables.to_dict())
131
+
132
+ return True, reply.messages[-1]
133
+
134
+ async def _ask_streaming(self, client: Client, message: Message) -> ResponseMessage | None:
135
+ connection_attemps = 1
136
+ try:
137
+ async for event in client.send_message(message):
138
+ result, task = self._process_event(event)
139
+ if not task:
140
+ return result
141
+ except httpx.ConnectError as e:
142
+ if task and connection_attemps < self._max_reconnects:
143
+ pass
144
+
145
+ if not self.__agent_card:
146
+ raise A2aClientError("Failed to connect to the agent: agent card not found") from e
147
+ raise A2aClientError(f"Failed to connect to the agent: {pformat(self.__agent_card.model_dump())}") from e
148
+
149
+ task = cast(Task, task)
150
+ while connection_attemps < self._max_reconnects:
151
+ try:
152
+ async for event in client.resubscribe(TaskIdParams(id=task.id)):
153
+ result, task = self._process_event(event)
154
+ if not task:
155
+ return result
156
+
157
+ except httpx.ConnectError as e:
158
+ connection_attemps += 1
159
+ if connection_attemps < self._max_reconnects:
160
+ pass
161
+
162
+ if not self.__agent_card:
163
+ raise A2aClientError("Failed to connect to the agent: agent card not found") from e
164
+ raise A2aClientError(
165
+ f"Failed to connect to the agent: {pformat(self.__agent_card.model_dump())}"
166
+ ) from e
167
+
168
+ return None
169
+
170
+ async def _ask_polling(self, client: Client, message: Message) -> ResponseMessage | None:
171
+ try:
172
+ async for event in client.send_message(message):
173
+ result, started_task = self._process_event(event)
174
+ if not started_task:
175
+ return result
176
+ break
177
+ except httpx.ConnectError as e:
178
+ if not self.__agent_card:
179
+ raise A2aClientError("Failed to connect to the agent: agent card not found") from e
180
+ raise A2aClientError(f"Failed to connect to the agent: {pformat(self.__agent_card.model_dump())}") from e
181
+
182
+ started_task, connection_attemps = cast(Task, started_task), 0
183
+ while connection_attemps < self._max_reconnects:
184
+ while True:
185
+ try:
186
+ task = await client.get_task(TaskQueryParams(id=started_task.id))
187
+
188
+ except httpx.ConnectError as e:
189
+ connection_attemps += 1
190
+ if connection_attemps < self._max_reconnects:
191
+ pass
192
+
193
+ if not self.__agent_card:
194
+ raise A2aClientError("Failed to connect to the agent: agent card not found") from e
195
+ raise A2aClientError(
196
+ f"Failed to connect to the agent: {pformat(self.__agent_card.model_dump())}"
197
+ ) from e
198
+
199
+ else:
200
+ if _is_task_completed(task):
201
+ return response_message_from_a2a_artifacts(task.artifacts)
202
+
203
+ await asyncio.sleep(self._polling_interval)
204
+
205
+ return None
206
+
207
+ def _process_event(self, event: ClientEvent | Message) -> tuple[ResponseMessage | None, Task | None]:
208
+ if isinstance(event, Message):
209
+ return response_message_from_a2a_message(event), None
210
+
211
+ task, _ = event
212
+ if _is_task_completed(task):
213
+ return response_message_from_a2a_artifacts(task.artifacts), None
214
+
215
+ return None, task
216
+
217
+ def update_tool_signature(
218
+ self,
219
+ tool_sig: str | dict[str, Any],
220
+ is_remove: bool,
221
+ silent_override: bool = False,
222
+ ) -> None:
223
+ self.__llm_config = self._update_tool_config(
224
+ self.__llm_config,
225
+ tool_sig=tool_sig,
226
+ is_remove=is_remove,
227
+ silent_override=silent_override,
228
+ )
229
+
230
+ async def _get_agent_card(
231
+ self,
232
+ auth_http_kwargs: dict[str, Any] | None = None,
233
+ ) -> AgentCard:
234
+ resolver = A2ACardResolver(httpx_client=self._httpx_client_factory(), base_url=self.url)
235
+
236
+ card: AgentCard | None = None
237
+
238
+ try:
239
+ logger.info(f"Attempting to fetch public agent card from: {self.url}{AGENT_CARD_WELL_KNOWN_PATH}")
240
+
241
+ try:
242
+ card = await resolver.get_agent_card(relative_card_path=AGENT_CARD_WELL_KNOWN_PATH)
243
+ except A2AClientHTTPError as e_public:
244
+ if e_public.status_code == 404:
245
+ logger.info(
246
+ f"Attempting to fetch public agent card from: {self.url}{PREV_AGENT_CARD_WELL_KNOWN_PATH}"
247
+ )
248
+ card = await resolver.get_agent_card(relative_card_path=PREV_AGENT_CARD_WELL_KNOWN_PATH)
249
+ else:
250
+ raise e_public
251
+
252
+ if card.supports_authenticated_extended_card:
253
+ try:
254
+ card = await resolver.get_agent_card(
255
+ relative_card_path=EXTENDED_AGENT_CARD_PATH,
256
+ http_kwargs=auth_http_kwargs,
257
+ )
258
+ except Exception as e_extended:
259
+ logger.warning(
260
+ f"Failed to fetch extended agent card: {e_extended}. Will proceed with public card.",
261
+ exc_info=True,
262
+ )
263
+
264
+ except Exception as e:
265
+ raise A2aAgentNotFoundError(self.name) from e
266
+
267
+ return card
268
+
269
+
270
+ def _is_task_completed(task: Task) -> bool:
271
+ if task.status.state is TaskState.failed:
272
+ raise A2aClientError(f"Task failed: {pformat(task.model_dump())}")
273
+
274
+ if task.status.state is TaskState.rejected:
275
+ raise A2aClientError(f"Task rejected: {pformat(task.model_dump())}")
276
+
277
+ return task.status.state in (
278
+ TaskState.completed,
279
+ TaskState.canceled,
280
+ )