rasa-pro 3.14.0.dev7__py3-none-any.whl → 3.14.0.dev9__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 rasa-pro might be problematic. Click here for more details.

Files changed (471) hide show
  1. rasa/agents/agent_manager.py +1 -1
  2. rasa/agents/constants.py +2 -2
  3. rasa/agents/protocol/a2a/a2a_agent.py +385 -227
  4. rasa/agents/protocol/mcp/mcp_base_agent.py +30 -13
  5. rasa/agents/protocol/mcp/mcp_open_agent.py +31 -8
  6. rasa/agents/protocol/mcp/mcp_task_agent.py +32 -9
  7. rasa/agents/schemas/agent_output.py +1 -1
  8. rasa/agents/utils.py +90 -1
  9. rasa/builder/README.md +120 -0
  10. rasa/builder/__init__.py +0 -0
  11. rasa/builder/auth.py +176 -0
  12. rasa/builder/config.py +92 -0
  13. rasa/builder/copilot/__init__.py +0 -0
  14. rasa/builder/copilot/constants.py +31 -0
  15. rasa/builder/copilot/copilot.py +450 -0
  16. rasa/builder/copilot/copilot_response_handler.py +522 -0
  17. rasa/builder/copilot/copilot_templated_message_provider.py +58 -0
  18. rasa/builder/copilot/exceptions.py +32 -0
  19. rasa/builder/copilot/models.py +500 -0
  20. rasa/builder/copilot/prompts/__init__.py +0 -0
  21. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +766 -0
  22. rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
  23. rasa/builder/copilot/signing.py +305 -0
  24. rasa/builder/copilot/telemetry.py +210 -0
  25. rasa/builder/copilot/templated_messages/__init__.py +0 -0
  26. rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
  27. rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +38 -0
  28. rasa/builder/document_retrieval/__init__.py +0 -0
  29. rasa/builder/document_retrieval/constants.py +15 -0
  30. rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
  31. rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
  32. rasa/builder/document_retrieval/models.py +62 -0
  33. rasa/builder/download.py +140 -0
  34. rasa/builder/exceptions.py +91 -0
  35. rasa/builder/guardrails/__init__.py +1 -0
  36. rasa/builder/guardrails/constants.py +9 -0
  37. rasa/builder/guardrails/exceptions.py +4 -0
  38. rasa/builder/guardrails/lakera.py +206 -0
  39. rasa/builder/guardrails/models.py +231 -0
  40. rasa/builder/guardrails/store.py +238 -0
  41. rasa/builder/guardrails/utils.py +328 -0
  42. rasa/builder/job_manager.py +87 -0
  43. rasa/builder/jobs.py +282 -0
  44. rasa/builder/llm_service.py +246 -0
  45. rasa/builder/logging_utils.py +265 -0
  46. rasa/builder/main.py +243 -0
  47. rasa/builder/models.py +216 -0
  48. rasa/builder/project_generator.py +458 -0
  49. rasa/builder/project_info.py +72 -0
  50. rasa/builder/scrape_rasa_docs.py +97 -0
  51. rasa/builder/service.py +1345 -0
  52. rasa/builder/shared/tracker_context.py +212 -0
  53. rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
  54. rasa/builder/template_cache.py +244 -0
  55. rasa/builder/training_service.py +194 -0
  56. rasa/builder/validation_service.py +97 -0
  57. rasa/cli/project_templates/basic/README.md +23 -0
  58. rasa/cli/project_templates/basic/actions/__init__ +0 -0
  59. rasa/cli/project_templates/basic/actions/action_human_handoff.py +40 -0
  60. rasa/cli/project_templates/basic/actions/actions.md +10 -0
  61. rasa/cli/project_templates/basic/config.yml +29 -0
  62. rasa/cli/project_templates/basic/credentials.yml +33 -0
  63. rasa/cli/project_templates/basic/data/data.md +9 -0
  64. rasa/cli/project_templates/basic/data/general/feedback.yml +21 -0
  65. rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
  66. rasa/cli/project_templates/basic/data/general/hello.yml +6 -0
  67. rasa/cli/project_templates/basic/data/general/help.yml +6 -0
  68. rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
  69. rasa/cli/project_templates/basic/data/general/show_faqs.yml +6 -0
  70. rasa/cli/project_templates/basic/data/system/patterns/pattern_cannot_handle.yml +7 -0
  71. rasa/cli/project_templates/basic/data/system/patterns/pattern_completed.yml +7 -0
  72. rasa/cli/project_templates/basic/data/system/patterns/pattern_correction.yml +7 -0
  73. rasa/cli/project_templates/basic/data/system/patterns/pattern_search.yml +8 -0
  74. rasa/cli/project_templates/basic/data/system/patterns/pattern_session_start.yml +8 -0
  75. rasa/cli/project_templates/basic/docs/docs.md +5 -0
  76. rasa/cli/project_templates/basic/docs/template.txt +28 -0
  77. rasa/cli/project_templates/basic/domain/domain.md +8 -0
  78. rasa/cli/project_templates/basic/domain/general/feedback.yml +25 -0
  79. rasa/cli/project_templates/basic/domain/general/goodbye.yml +9 -0
  80. rasa/cli/project_templates/basic/domain/general/hello.yml +7 -0
  81. rasa/cli/project_templates/basic/domain/general/help.yml +21 -0
  82. rasa/cli/project_templates/basic/domain/general/human_handoff.yml +32 -0
  83. rasa/cli/project_templates/basic/domain/general/show_faqs.yml +14 -0
  84. rasa/cli/project_templates/basic/domain/system/patterns/pattern_cannot_handle.yml +5 -0
  85. rasa/cli/project_templates/basic/domain/system/patterns/pattern_session_start.yml +19 -0
  86. rasa/cli/project_templates/basic/endpoints.yml +67 -0
  87. rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
  88. rasa/cli/project_templates/default/config.yml +4 -0
  89. rasa/cli/project_templates/default/endpoints.yml +4 -0
  90. rasa/cli/project_templates/finance/README.md +25 -0
  91. rasa/cli/project_templates/finance/actions/__init__.py +46 -0
  92. rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
  93. rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +47 -0
  94. rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +40 -0
  95. rasa/cli/project_templates/finance/actions/action_session_start.py +74 -0
  96. rasa/cli/project_templates/finance/actions/actions.md +15 -0
  97. rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
  98. rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +48 -0
  99. rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +36 -0
  100. rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +54 -0
  101. rasa/cli/project_templates/finance/actions/database.py +277 -0
  102. rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
  103. rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +52 -0
  104. rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +51 -0
  105. rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +40 -0
  106. rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +40 -0
  107. rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +46 -0
  108. rasa/cli/project_templates/finance/actions/transfers/action_process_immediate_payment.py +18 -0
  109. rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +49 -0
  110. rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +19 -0
  111. rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +36 -0
  112. rasa/cli/project_templates/finance/config.yml +23 -0
  113. rasa/cli/project_templates/finance/credentials.yml +32 -0
  114. rasa/cli/project_templates/finance/csvs/accounts.csv +8 -0
  115. rasa/cli/project_templates/finance/csvs/advisors.csv +7 -0
  116. rasa/cli/project_templates/finance/csvs/appointments.csv +211 -0
  117. rasa/cli/project_templates/finance/csvs/branches.csv +10 -0
  118. rasa/cli/project_templates/finance/csvs/cards.csv +11 -0
  119. rasa/cli/project_templates/finance/csvs/payees.csv +11 -0
  120. rasa/cli/project_templates/finance/csvs/transactions.csv +71 -0
  121. rasa/cli/project_templates/finance/csvs/users.csv +4 -0
  122. rasa/cli/project_templates/finance/data/accounts/check_balance.yml +10 -0
  123. rasa/cli/project_templates/finance/data/cards/block_card.yml +66 -0
  124. rasa/cli/project_templates/finance/data/cards/select_card.yml +12 -0
  125. rasa/cli/project_templates/finance/data/data.md +11 -0
  126. rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
  127. rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
  128. rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
  129. rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
  130. rasa/cli/project_templates/finance/data/general/help.yml +9 -0
  131. rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
  132. rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
  133. rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +5 -0
  134. rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
  135. rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
  136. rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
  137. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
  138. rasa/cli/project_templates/finance/data/system/source/accounts.json +51 -0
  139. rasa/cli/project_templates/finance/data/system/source/advisors.json +44 -0
  140. rasa/cli/project_templates/finance/data/system/source/appointments.json +1474 -0
  141. rasa/cli/project_templates/finance/data/system/source/branches.json +47 -0
  142. rasa/cli/project_templates/finance/data/system/source/cards.json +72 -0
  143. rasa/cli/project_templates/finance/data/system/source/payees.json +74 -0
  144. rasa/cli/project_templates/finance/data/system/source/transactions.json +492 -0
  145. rasa/cli/project_templates/finance/data/system/source/users.json +29 -0
  146. rasa/cli/project_templates/finance/data/transfers/add_payee.yml +29 -0
  147. rasa/cli/project_templates/finance/data/transfers/list_payees.yml +5 -0
  148. rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +21 -0
  149. rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +67 -0
  150. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +8 -0
  151. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +8 -0
  152. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +8 -0
  153. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +8 -0
  154. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +8 -0
  155. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +7 -0
  156. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +8 -0
  157. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +8 -0
  158. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +8 -0
  159. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +8 -0
  160. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +8 -0
  161. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +8 -0
  162. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +8 -0
  163. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +8 -0
  164. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +8 -0
  165. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +8 -0
  166. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +8 -0
  167. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +8 -0
  168. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +8 -0
  169. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +8 -0
  170. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +50 -0
  171. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +50 -0
  172. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +48 -0
  173. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +50 -0
  174. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +50 -0
  175. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +47 -0
  176. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +50 -0
  177. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +50 -0
  178. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +47 -0
  179. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +50 -0
  180. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +50 -0
  181. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +50 -0
  182. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +47 -0
  183. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +50 -0
  184. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +50 -0
  185. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +47 -0
  186. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +50 -0
  187. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +50 -0
  188. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +47 -0
  189. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +50 -0
  190. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +50 -0
  191. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +47 -0
  192. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +47 -0
  193. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +50 -0
  194. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +50 -0
  195. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +47 -0
  196. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +50 -0
  197. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +50 -0
  198. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +47 -0
  199. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +50 -0
  200. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +50 -0
  201. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +47 -0
  202. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +50 -0
  203. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +50 -0
  204. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +50 -0
  205. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +47 -0
  206. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +50 -0
  207. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +50 -0
  208. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +47 -0
  209. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +50 -0
  210. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +50 -0
  211. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +47 -0
  212. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +50 -0
  213. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +50 -0
  214. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +50 -0
  215. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +47 -0
  216. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +50 -0
  217. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +50 -0
  218. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +47 -0
  219. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +50 -0
  220. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +50 -0
  221. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +47 -0
  222. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +50 -0
  223. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +50 -0
  224. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +47 -0
  225. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +47 -0
  226. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +50 -0
  227. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +50 -0
  228. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +50 -0
  229. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +50 -0
  230. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +47 -0
  231. rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +11 -0
  232. rasa/cli/project_templates/finance/domain/cards/block_card.yml +101 -0
  233. rasa/cli/project_templates/finance/domain/cards/select_card.yml +12 -0
  234. rasa/cli/project_templates/finance/domain/domain.md +10 -0
  235. rasa/cli/project_templates/finance/domain/general/agent_details.yml +12 -0
  236. rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
  237. rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
  238. rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
  239. rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
  240. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  241. rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
  242. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
  243. rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
  244. rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
  245. rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +47 -0
  246. rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +4 -0
  247. rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +16 -0
  248. rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +79 -0
  249. rasa/cli/project_templates/finance/endpoints.yml +66 -0
  250. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
  251. rasa/cli/project_templates/telco/README.md +25 -0
  252. rasa/cli/project_templates/telco/actions/__init__.py +0 -0
  253. rasa/cli/project_templates/telco/actions/actions.md +12 -0
  254. rasa/cli/project_templates/telco/actions/billing/__init__.py +0 -0
  255. rasa/cli/project_templates/telco/actions/billing/actions_billing.py +204 -0
  256. rasa/cli/project_templates/telco/actions/general/__init__.py +0 -0
  257. rasa/cli/project_templates/telco/actions/general/action_human_handoff.py +49 -0
  258. rasa/cli/project_templates/telco/actions/network/__init__.py +0 -0
  259. rasa/cli/project_templates/telco/actions/network/actions_get_data_from_db.py +48 -0
  260. rasa/cli/project_templates/telco/actions/network/actions_run_diagnostics.py +28 -0
  261. rasa/cli/project_templates/telco/actions/network/actions_session_start.py +18 -0
  262. rasa/cli/project_templates/telco/config.yml +29 -0
  263. rasa/cli/project_templates/telco/credentials.yml +33 -0
  264. rasa/cli/project_templates/telco/csvs/billing.csv +19 -0
  265. rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
  266. rasa/cli/project_templates/telco/data/billing/flow_understand_bill.yml +45 -0
  267. rasa/cli/project_templates/telco/data/data.md +11 -0
  268. rasa/cli/project_templates/telco/data/general/bot_challenge.yml +6 -0
  269. rasa/cli/project_templates/telco/data/general/feedback.yml +20 -0
  270. rasa/cli/project_templates/telco/data/general/goodbye.yml +6 -0
  271. rasa/cli/project_templates/telco/data/general/hello.yml +6 -0
  272. rasa/cli/project_templates/telco/data/general/human_handoff.yml +16 -0
  273. rasa/cli/project_templates/telco/data/general/patterns.yml +30 -0
  274. rasa/cli/project_templates/telco/data/network/flow_reboot_router.yml +8 -0
  275. rasa/cli/project_templates/telco/data/network/flow_reset_router.yml +7 -0
  276. rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +73 -0
  277. rasa/cli/project_templates/telco/docs/docs.md +5 -0
  278. rasa/cli/project_templates/telco/docs/network/reset_vs_rboot_router.txt +1 -0
  279. rasa/cli/project_templates/telco/docs/network/restart_router.txt +6 -0
  280. rasa/cli/project_templates/telco/docs/network/run_speed_test.txt +6 -0
  281. rasa/cli/project_templates/telco/domain/billing/understand_bill.yml +102 -0
  282. rasa/cli/project_templates/telco/domain/domain.md +14 -0
  283. rasa/cli/project_templates/telco/domain/general/bot_challenge.yml +4 -0
  284. rasa/cli/project_templates/telco/domain/general/feedback.yml +25 -0
  285. rasa/cli/project_templates/telco/domain/general/goodbye.yml +7 -0
  286. rasa/cli/project_templates/telco/domain/general/hello.yml +5 -0
  287. rasa/cli/project_templates/telco/domain/general/human_handoff.yml +26 -0
  288. rasa/cli/project_templates/telco/domain/general/patterns.yml +33 -0
  289. rasa/cli/project_templates/telco/domain/network/reboot_router.yml +21 -0
  290. rasa/cli/project_templates/telco/domain/network/reset_router.yml +12 -0
  291. rasa/cli/project_templates/telco/domain/network/run_speed_test.yml +25 -0
  292. rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +75 -0
  293. rasa/cli/project_templates/telco/domain/shared.yml +129 -0
  294. rasa/cli/project_templates/telco/endpoints.yml +67 -0
  295. rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +40 -0
  296. rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
  297. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
  298. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
  299. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
  300. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
  301. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
  302. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
  303. rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
  304. rasa/cli/project_templates/tutorial/config.yml +2 -1
  305. rasa/cli/scaffold.py +46 -2
  306. rasa/core/actions/action.py +0 -1
  307. rasa/core/available_agents.py +2 -0
  308. rasa/core/available_endpoints.py +17 -2
  309. rasa/core/channels/channel.py +4 -3
  310. rasa/core/channels/constants.py +3 -0
  311. rasa/core/channels/development_inspector.py +2 -22
  312. rasa/core/channels/inspector/README.md +26 -14
  313. rasa/core/channels/inspector/dist/assets/{arc-cce7e0a8.js → arc-edef10dd.js} +1 -1
  314. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-e2a49be7.js → blockDiagram-38ab4fdb-49f6762b.js} +1 -1
  315. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-3def7895.js → c4Diagram-3d4e48cf-313c08e6.js} +1 -1
  316. rasa/core/channels/inspector/dist/assets/channel-63aa27d1.js +1 -0
  317. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-e66fe4df.js → classDiagram-70f12bd4-35e41ce9.js} +1 -1
  318. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-eb874aaa.js → classDiagram-v2-f2320105-f346068d.js} +1 -1
  319. rasa/core/channels/inspector/dist/assets/clone-5566bae8.js +1 -0
  320. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-cf934643.js → createText-2e5e7dd3-7a44bce8.js} +1 -1
  321. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-8fdf9155.js → edges-e0da2a9e-d7cf78c7.js} +1 -1
  322. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-6106fb96.js → erDiagram-9861fffd-9813e81c.js} +1 -1
  323. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4c2bb040.js → flowDb-956e92f1-d8ba0870.js} +1 -1
  324. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f0ff96af.js → flowDiagram-66a62f08-51f0db4d.js} +1 -1
  325. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-32936074.js +1 -0
  326. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-a21707ec.js → flowchart-elk-definition-4a651766-ff9ea384.js} +1 -1
  327. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-c165acb1.js → ganttDiagram-c361ad54-a8e13b6b.js} +1 -1
  328. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-b0564cf1.js → gitGraphDiagram-72cf32ee-3b171c6d.js} +1 -1
  329. rasa/core/channels/inspector/dist/assets/{graph-e557e67a.js → graph-790ef78b.js} +1 -1
  330. rasa/core/channels/inspector/dist/assets/{index-3862675e-1ce60e9e.js → index-3862675e-ecdce073.js} +1 -1
  331. rasa/core/channels/inspector/dist/assets/index-d705da80.js +1352 -0
  332. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-893569e2.js → infoDiagram-f8f76790-f5a422fe.js} +1 -1
  333. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-c29c864f.js → journeyDiagram-49397b02-3185b7ac.js} +1 -1
  334. rasa/core/channels/inspector/dist/assets/{layout-649a5eae.js → layout-837fd3aa.js} +1 -1
  335. rasa/core/channels/inspector/dist/assets/{line-0e5685ed.js → line-7e05afcb.js} +1 -1
  336. rasa/core/channels/inspector/dist/assets/{linear-eaa320bd.js → linear-162eb295.js} +1 -1
  337. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-f35df9e6.js → mindmap-definition-fc14e90a-f4978aee.js} +1 -1
  338. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78339e96.js → pieDiagram-8a3498a8-b25d0a52.js} +1 -1
  339. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-9b5f2f14.js → quadrantDiagram-120e2f19-63db1afa.js} +1 -1
  340. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d05ddb3a.js → requirementDiagram-deff3bca-1b486cc9.js} +1 -1
  341. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-d9be5dfd.js → sankeyDiagram-04a897e0-7e795291.js} +1 -1
  342. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-0f1c4348.js → sequenceDiagram-704730f1-b8aba159.js} +1 -1
  343. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-9ddf63b3.js → stateDiagram-587899a1-41529fd5.js} +1 -1
  344. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-bc2b81ed.js → stateDiagram-v2-d93cdb3a-b241043c.js} +1 -1
  345. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0a287936.js → styles-6aaf32cf-b5b53234.js} +1 -1
  346. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-e3941990.js → styles-9a916d00-13d138e5.js} +1 -1
  347. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-ce4eca24.js → styles-c10674c1-94cbde3f.js} +1 -1
  348. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-d822b1a8.js → svgDrawCommon-08f97a94-453ae764.js} +1 -1
  349. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-e144c7a7.js → timeline-definition-85554ec2-8dcb88a4.js} +1 -1
  350. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-ab7f4e14.js → xychartDiagram-e933f94c-376af5f0.js} +1 -1
  351. rasa/core/channels/inspector/dist/index.html +2 -2
  352. rasa/core/channels/inspector/index.html +1 -1
  353. rasa/core/channels/inspector/src/App.tsx +16 -42
  354. rasa/core/channels/inspector/src/components/Chat.tsx +2 -3
  355. rasa/core/channels/inspector/src/components/DialogueHistoryStack.tsx +1 -0
  356. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +20 -3
  357. rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
  358. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +14 -0
  359. rasa/core/channels/inspector/src/types.ts +32 -7
  360. rasa/core/channels/socketio.py +212 -51
  361. rasa/core/channels/studio_chat.py +59 -57
  362. rasa/core/channels/voice_stream/asr/asr_event.py +1 -1
  363. rasa/core/channels/voice_stream/asr/azure.py +6 -3
  364. rasa/core/channels/voice_stream/asr/deepgram.py +1 -1
  365. rasa/core/channels/voice_stream/audiocodes.py +3 -0
  366. rasa/core/channels/voice_stream/browser_audio.py +53 -3
  367. rasa/core/channels/voice_stream/genesys.py +2 -1
  368. rasa/core/channels/voice_stream/jambonz.py +9 -1
  369. rasa/core/channels/voice_stream/twilio_media_streams.py +16 -0
  370. rasa/core/channels/voice_stream/voice_channel.py +66 -3
  371. rasa/core/constants.py +6 -0
  372. rasa/core/iam_credentials_providers/__init__.py +0 -0
  373. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
  374. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
  375. rasa/core/policies/enterprise_search_policy.py +4 -7
  376. rasa/core/policies/flows/flow_executor.py +14 -5
  377. rasa/core/policies/ted_policy.py +7 -5
  378. rasa/core/processor.py +32 -0
  379. rasa/core/redis_connection_factory.py +411 -0
  380. rasa/core/run.py +13 -3
  381. rasa/core/tracker_stores/redis_tracker_store.py +32 -14
  382. rasa/core/tracker_stores/sql_tracker_store.py +57 -1
  383. rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
  384. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +10 -5
  385. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +10 -5
  386. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +20 -12
  387. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +19 -12
  388. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +6 -35
  389. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  390. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +1 -1
  391. rasa/dialogue_understanding/processor/command_processor.py +35 -0
  392. rasa/engine/graph.py +5 -1
  393. rasa/engine/recipes/default_components.py +78 -10
  394. rasa/engine/recipes/default_recipe.py +41 -1
  395. rasa/engine/storage/local_model_storage.py +83 -3
  396. rasa/graph_components/validators/default_recipe_validator.py +153 -135
  397. rasa/model_manager/model_api.py +4 -5
  398. rasa/model_manager/runner_service.py +1 -1
  399. rasa/model_manager/socket_bridge.py +20 -15
  400. rasa/model_manager/trainer_service.py +12 -9
  401. rasa/model_manager/utils.py +1 -29
  402. rasa/model_manager/warm_rasa_process.py +1 -1
  403. rasa/model_training.py +14 -0
  404. rasa/nlu/classifiers/diet_classifier.py +22 -6
  405. rasa/nlu/classifiers/logistic_regression_classifier.py +18 -0
  406. rasa/nlu/extractors/extractor.py +1 -2
  407. rasa/shared/agents/auth/__init__.py +0 -0
  408. rasa/shared/agents/auth/agent_auth_factory.py +74 -0
  409. rasa/shared/agents/auth/agent_auth_manager.py +86 -0
  410. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  411. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  412. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  413. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  414. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +159 -0
  415. rasa/shared/agents/auth/constants.py +11 -0
  416. rasa/shared/agents/auth/types.py +11 -0
  417. rasa/shared/core/constants.py +1 -0
  418. rasa/shared/core/domain.py +58 -11
  419. rasa/shared/core/events.py +2 -0
  420. rasa/shared/core/flows/constants.py +5 -0
  421. rasa/shared/core/flows/flow_step.py +7 -1
  422. rasa/shared/core/flows/flows_list.py +6 -0
  423. rasa/shared/core/flows/steps/call.py +15 -12
  424. rasa/shared/core/flows/validation.py +238 -44
  425. rasa/shared/core/flows/yaml_flows_io.py +15 -6
  426. rasa/shared/core/slots.py +4 -0
  427. rasa/shared/exceptions.py +12 -0
  428. rasa/shared/importers/importer.py +6 -0
  429. rasa/shared/importers/utils.py +77 -1
  430. rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
  431. rasa/shared/providers/_utils.py +60 -44
  432. rasa/shared/providers/embedding/default_litellm_embedding_client.py +2 -0
  433. rasa/shared/providers/llm/_base_litellm_client.py +2 -2
  434. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -0
  435. rasa/shared/providers/llm/llm_response.py +4 -4
  436. rasa/shared/utils/common.py +24 -0
  437. rasa/shared/utils/llm.py +2 -1
  438. rasa/shared/utils/mcp/server_connection.py +84 -23
  439. rasa/shared/utils/mcp/utils.py +20 -0
  440. rasa/studio/upload.py +16 -47
  441. rasa/telemetry.py +97 -23
  442. rasa/tracing/config.py +38 -12
  443. rasa/tracing/instrumentation/attribute_extractors.py +5 -1
  444. rasa/tracing/instrumentation/instrumentation.py +85 -8
  445. rasa/utils/common.py +1 -1
  446. rasa/utils/io.py +27 -9
  447. rasa/utils/json_utils.py +6 -1
  448. rasa/utils/log_utils.py +5 -1
  449. rasa/utils/openapi.py +144 -0
  450. rasa/utils/tensorflow/__init__.py +29 -0
  451. rasa/utils/tensorflow/callback.py +1 -1
  452. rasa/utils/tensorflow/crf.py +1 -1
  453. rasa/utils/tensorflow/data_generator.py +21 -8
  454. rasa/utils/tensorflow/layers.py +11 -4
  455. rasa/utils/tensorflow/metrics.py +7 -3
  456. rasa/utils/tensorflow/models.py +41 -6
  457. rasa/utils/tensorflow/rasa_layers.py +6 -4
  458. rasa/utils/tensorflow/transformer.py +2 -3
  459. rasa/utils/train_utils.py +68 -38
  460. rasa/validator.py +18 -16
  461. rasa/version.py +1 -1
  462. rasa_pro-3.14.0.dev9.dist-info/METADATA +199 -0
  463. {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/RECORD +466 -156
  464. rasa/core/channels/inspector/dist/assets/channel-858c2c20.js +0 -1
  465. rasa/core/channels/inspector/dist/assets/clone-4b80996c.js +0 -1
  466. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-16f09b7a.js +0 -1
  467. rasa/core/channels/inspector/dist/assets/index-996fe816.js +0 -1353
  468. rasa_pro-3.14.0.dev7.dist-info/METADATA +0 -190
  469. {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/NOTICE +0 -0
  470. {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/WHEEL +0 -0
  471. {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev9.dist-info}/entry_points.txt +0 -0
@@ -1,50 +1,49 @@
1
1
  import asyncio
2
2
  import json
3
3
  import os
4
+ import time
4
5
  import uuid
5
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, ClassVar, Dict, List, Optional
6
7
  from urllib.parse import urlparse
7
8
 
8
9
  import httpx
9
10
  import structlog
10
11
  from a2a.client import (
11
12
  A2ACardResolver,
12
- A2AClient,
13
13
  A2AClientError,
14
14
  A2AClientHTTPError,
15
15
  A2AClientJSONError,
16
+ Client,
17
+ ClientConfig,
18
+ ClientEvent,
19
+ ClientFactory,
16
20
  )
21
+ from a2a.client.errors import A2AClientJSONRPCError
17
22
  from a2a.types import (
18
- AgentCapabilities,
19
23
  AgentCard,
20
- AgentSkill,
24
+ Artifact,
21
25
  DataPart,
22
26
  FilePart,
23
27
  FileWithUri,
24
28
  InternalError,
25
29
  InvalidAgentResponseError,
26
- JSONRPCErrorResponse,
27
30
  Message,
28
- MessageSendConfiguration,
29
- MessageSendParams,
30
31
  Part,
31
32
  Role,
32
- SendStreamingMessageRequest,
33
- SendStreamingMessageResponse,
34
33
  Task,
35
- TaskArtifactUpdateEvent,
34
+ TaskQueryParams,
36
35
  TaskState,
37
- TaskStatus,
38
- TaskStatusUpdateEvent,
39
36
  TextPart,
37
+ TransportProtocol,
40
38
  )
39
+ from pydantic import ValidationError
41
40
 
42
41
  from rasa.agents.constants import (
43
42
  A2A_AGENT_CONTEXT_ID_KEY,
44
43
  A2A_AGENT_TASK_ID_KEY,
45
44
  AGENT_DEFAULT_MAX_RETRIES,
46
45
  AGENT_DEFAULT_TIMEOUT_SECONDS,
47
- AGENT_METADATA_TOOL_RESULTS_KEY,
46
+ AGENT_METADATA_STRUCTURED_RESULTS_KEY,
48
47
  MAX_AGENT_RETRY_DELAY_SECONDS,
49
48
  )
50
49
  from rasa.agents.core.agent_protocol import AgentProtocol
@@ -57,12 +56,21 @@ from rasa.shared.exceptions import (
57
56
  RasaException,
58
57
  )
59
58
 
59
+ A2A_TASK_POOLING_INITIAL_DELAY = 0.5
60
+ A2A_TASK_POOLING_MAX_WAIT = 60
61
+
60
62
  structlogger = structlog.get_logger()
61
63
 
62
64
 
63
65
  class A2AAgent(AgentProtocol):
64
66
  """A2A client implementation"""
65
67
 
68
+ __SUPPORTED_OUTPUT_MODES: ClassVar[list[str]] = [
69
+ "text",
70
+ "text/plain",
71
+ "application/json",
72
+ ]
73
+
66
74
  def __init__(
67
75
  self,
68
76
  name: str,
@@ -78,7 +86,7 @@ class A2AAgent(AgentProtocol):
78
86
  self._max_retries = max_retries
79
87
 
80
88
  self.agent_card: Optional[AgentCard] = None
81
- self._client: Optional[A2AClient] = None
89
+ self._client: Optional[Client] = None
82
90
 
83
91
  @classmethod
84
92
  def from_config(cls, config: AgentConfig) -> AgentProtocol:
@@ -132,15 +140,12 @@ class A2AAgent(AgentProtocol):
132
140
  )
133
141
 
134
142
  try:
135
- self._client = A2AClient(
136
- httpx.AsyncClient(timeout=self._timeout), agent_card=self.agent_card
137
- )
143
+ self._client = self._init_client()
138
144
  structlogger.debug(
139
- "a2a_agent.connect.success",
140
- event_info=f"Connected to A2A server '{self._name}' "
141
- f"at {self.agent_card.url}",
145
+ "a2a_agent.connect.agent_client_initialized",
146
+ event_info=f"Initialized A2A client for agent '{self._name}'. "
147
+ f"Performing health check using the URL {self.agent_card.url}",
142
148
  )
143
- # TODO: Make a test request to /tasks to verify the connection
144
149
  except Exception as exception:
145
150
  structlogger.error(
146
151
  "a2a_agent.connect.error",
@@ -153,6 +158,13 @@ class A2AAgent(AgentProtocol):
153
158
  f"'{self._name}': {exception}"
154
159
  ) from exception
155
160
 
161
+ await self._perform_health_check()
162
+ structlogger.debug(
163
+ "a2a_agent.connect.success",
164
+ event_info=f"Connected to A2A server '{self._name}' "
165
+ f"at {self.agent_card.url}",
166
+ )
167
+
156
168
  async def disconnect(self) -> None:
157
169
  """We don't need to explicitly disconnect the A2A client"""
158
170
  return
@@ -167,7 +179,7 @@ class A2AAgent(AgentProtocol):
167
179
  if not self._client or not self.agent_card:
168
180
  structlogger.error(
169
181
  "a2a_agent.run.error",
170
- event_info="A2A client is not initialized. " "Call connect() first.",
182
+ event_info="A2A client is not initialized. Call connect() first.",
171
183
  )
172
184
  return AgentOutput(
173
185
  id=agent_input.id,
@@ -175,121 +187,129 @@ class A2AAgent(AgentProtocol):
175
187
  error_message="Client not initialized",
176
188
  )
177
189
 
178
- if self.agent_card.capabilities.streaming:
179
- structlogger.info(
180
- "a2a_agent.run.streaming",
181
- event_info="Running A2A agent in streaming mode",
182
- agent_name=self._name,
183
- )
184
- return await self._run_streaming_agent(agent_input)
185
- else:
186
- # we dont support non-streaming mode yet
190
+ structlogger.info(
191
+ "a2a_agent.run.start",
192
+ event_info="Running A2A agent",
193
+ agent_name=self._name,
194
+ )
195
+ message = self._prepare_message(agent_input)
196
+
197
+ task_id: Optional[str] = None
198
+ events_received = 0
199
+ try:
200
+ async for event in self._client.send_message(message):
201
+ events_received += 1
202
+ agent_output = self._handle_send_message_response(agent_input, event)
203
+ if agent_output is not None:
204
+ return agent_output
205
+ else:
206
+ # Not a terminal response, save taskID (in case that's the only
207
+ # event, and we need to pool) and continue waiting for next events
208
+ if (
209
+ isinstance(event, tuple)
210
+ and len(event) == 2
211
+ and isinstance(event[0], Task)
212
+ ):
213
+ task_id = event[0].id
214
+ continue
215
+ except A2AClientJSONRPCError as e:
216
+ return self._handle_json_rpc_error_response(agent_input, e.error)
217
+ except A2AClientError as exception:
187
218
  structlogger.error(
188
- "a2a_agent.run.error",
189
- event_info="Non-streaming mode is currently not supported",
219
+ "a2a_agent.run.send_message.error",
220
+ event_info="Error during sending message to A2A agent",
190
221
  agent_name=self._name,
222
+ error=str(exception),
191
223
  )
192
224
  return AgentOutput(
193
225
  id=agent_input.id,
194
226
  status=AgentStatus.FATAL_ERROR,
195
- error_message="Non-streaming mode is not supported",
227
+ error_message=f"Send message error: {exception!s}",
196
228
  )
197
229
 
198
- async def process_output(self, output: AgentOutput) -> AgentOutput:
199
- """Post-process the output before returning it to Rasa."""
200
- # A2A-specific output processing logic
201
- return output
202
-
203
- async def _run_streaming_agent(self, agent_input: AgentInput) -> AgentOutput:
204
- if not self._client:
230
+ # The stream has ended, but we didn't get a terminal response.
231
+ # Check if we received any events at all.
232
+ if events_received == 0:
205
233
  structlogger.error(
206
- "a2a_agent.run_streaming_agent.error",
207
- event_info="A2A client is not initialized. Call connect() first.",
234
+ "a2a_agent.run.no_events_received",
235
+ event_info="No events received from A2A agent after sending message",
236
+ agent_name=self._name,
208
237
  )
209
238
  return AgentOutput(
210
239
  id=agent_input.id,
211
- status=AgentStatus.FATAL_ERROR,
212
- error_message="Client not initialized",
240
+ status=AgentStatus.RECOVERABLE_ERROR,
241
+ error_message="No events received from A2A agent",
213
242
  )
214
- message_send_params = self._prepare_message_send_params(agent_input)
215
-
216
- try:
217
- async for response in self._client.send_message_streaming(
218
- SendStreamingMessageRequest(
219
- id=str(uuid.uuid4()), params=message_send_params
220
- )
221
- ):
222
- agent_output = self._handle_streaming_response(agent_input, response)
223
- if agent_output is not None:
224
- return agent_output
225
- else:
226
- # Not a terminal response, continue waiting for next responses
227
- continue
228
243
 
229
- except A2AClientError as exception:
244
+ # Now we need to poll the task until it reaches a terminal state.
245
+ if not task_id:
230
246
  structlogger.error(
231
- "a2a_agent.run_streaming_agent.error",
232
- event_info="Error during streaming message to A2A server",
247
+ "a2a_agent.run.pooling.missing_id",
248
+ event_info="Missing task_id for polling",
233
249
  agent_name=self._name,
234
- error=str(exception),
250
+ task_id=task_id,
235
251
  )
236
252
  return AgentOutput(
237
253
  id=agent_input.id,
238
254
  status=AgentStatus.FATAL_ERROR,
239
- error_message=f"Streaming error: {exception!s}",
255
+ error_message="Missing task_id for polling",
240
256
  )
241
-
242
- # In case we didn't receive any response or the stream ended unexpectedly
243
- structlogger.error(
244
- "a2a_agent.run_streaming_agent.unexpected_end",
245
- event_info="Unexpected end of streaming response from A2A server",
246
- agent_name=self._name,
247
- )
248
- return AgentOutput(
249
- id=agent_input.id,
250
- status=AgentStatus.FATAL_ERROR,
251
- error_message="Unexpected end of streaming response",
257
+ return await self._pool_task_until_terminal(
258
+ agent_input=agent_input,
259
+ task_id=task_id,
260
+ max_wait=A2A_TASK_POOLING_MAX_WAIT,
261
+ initial_delay=A2A_TASK_POOLING_INITIAL_DELAY,
262
+ max_delay=MAX_AGENT_RETRY_DELAY_SECONDS,
252
263
  )
253
264
 
254
- def _handle_streaming_response(
255
- self, agent_input: AgentInput, response: SendStreamingMessageResponse
265
+ async def process_output(self, output: AgentOutput) -> AgentOutput:
266
+ """Post-process the output before returning it to Rasa."""
267
+ # A2A-specific output processing logic
268
+ return output
269
+
270
+ def _handle_send_message_response(
271
+ self, agent_input: AgentInput, response: ClientEvent | Message
256
272
  ) -> Optional[AgentOutput]:
257
- """If the agent response is terminal (i.e., completed, failed, etc.),
273
+ """Handle possible response types from the A2A client:
274
+
275
+ In case of streaming, the response can be either exactly *one* Message,
276
+ or a *series* of tuples of (Task, Optional[TaskUpdateEvent]).
277
+
278
+ In case of pooling, the response can be either exactly *one* Message,
279
+ or exactly *one* tuple of (Task, None).
280
+
281
+ If the agent response is terminal (i.e., completed, failed, etc.),
258
282
  this method will return an AgentOutput.
259
283
  Otherwise, the task is still in progress (i.e., submitted, working), so this
260
284
  method will return None, so that the streaming or pooling agent can continue
261
285
  to wait for updates.
262
286
  """
263
- if isinstance(response.root, JSONRPCErrorResponse):
264
- return self._handle_json_rpc_error_response(agent_input, response.root)
265
-
266
- response_result = response.root.result
267
- if isinstance(response_result, Task):
268
- return self._handle_task_response(agent_input, response_result)
269
- elif isinstance(response_result, Message):
270
- return self._handle_message_response(response_result)
271
- elif isinstance(response_result, TaskStatusUpdateEvent):
272
- return self._handle_task_status_update_event(agent_input, response_result)
273
- elif isinstance(response_result, TaskArtifactUpdateEvent):
274
- return self._handle_task_artifact_update_event(agent_input, response_result)
287
+ if isinstance(response, Message):
288
+ return self._handle_message_response(agent_input, response)
289
+ elif (
290
+ isinstance(response, tuple)
291
+ and len(response) == 2
292
+ and isinstance(response[0], Task)
293
+ ):
294
+ return self._handle_client_event(agent_input, response)
275
295
  else:
276
296
  # Currently, no other response types exist, so this branch is
277
297
  # unreachable. It is kept as a safeguard against future changes
278
298
  # to the A2A protocol: if new response types are introduced,
279
299
  # the agent will log an error instead of crashing.
280
- return self._handle_unexpected_response_type(agent_input, response_result)
300
+ return self._handle_unexpected_response_type(agent_input, response)
281
301
 
282
302
  def _handle_json_rpc_error_response(
283
- self, agent_input: AgentInput, response: JSONRPCErrorResponse
303
+ self, agent_input: AgentInput, error: Any
284
304
  ) -> AgentOutput:
285
305
  structlogger.error(
286
- "a2a_agent.run_streaming_agent.error",
287
- event_info="Received error response from A2A server during streaming",
306
+ "a2a_agent.run.error",
307
+ event_info="Received JSON-RPC error response from A2A agent",
288
308
  agent_name=self._name,
289
- error=str(response.error),
309
+ error=str(error),
290
310
  )
291
311
  if isinstance(
292
- response.error,
312
+ error,
293
313
  (
294
314
  InternalError,
295
315
  InvalidAgentResponseError,
@@ -298,85 +318,53 @@ class A2AAgent(AgentProtocol):
298
318
  return AgentOutput(
299
319
  id=agent_input.id,
300
320
  status=AgentStatus.RECOVERABLE_ERROR,
301
- error_message=str(response.error),
321
+ error_message=str(error),
302
322
  )
303
323
  else:
304
324
  return AgentOutput(
305
325
  id=agent_input.id,
306
326
  status=AgentStatus.FATAL_ERROR,
307
- error_message=str(response.error),
327
+ error_message=str(error),
308
328
  )
309
329
 
310
- def _handle_task_response(
311
- self, agent_input: AgentInput, task: Task
330
+ def _handle_client_event(
331
+ self, agent_input: AgentInput, client_event: ClientEvent
312
332
  ) -> Optional[AgentOutput]:
333
+ task = client_event[0]
334
+ update_event = client_event[1]
313
335
  structlogger.debug(
314
- "a2a_agent.run_streaming_agent.task_received",
315
- event_info="Received task from A2A",
316
- agent_name=self._name,
336
+ "a2a_agent.run.client_event_received",
337
+ event_info="Received client event from A2A",
317
338
  task=task,
339
+ update_event=update_event,
318
340
  )
319
- agent_output = self._handle_task_status(
320
- agent_input=agent_input,
321
- context_id=task.context_id,
322
- task_id=task.id,
323
- task_status=task.status,
324
- )
325
- return agent_output
326
341
 
327
- def _handle_message_response(self, message: Message) -> Optional[AgentOutput]:
328
- # Message represents an intermediate conversational update,
329
- # we need to continue waiting for task updates
330
- structlogger.debug(
331
- "a2a_agent.run_streaming_agent.message_received",
332
- event_info="Received message from A2A",
333
- agent_name=self._name,
334
- message=message,
335
- )
336
- return None
342
+ return self._handle_task(agent_input=agent_input, task=task)
337
343
 
338
- def _handle_task_status_update_event(
339
- self, agent_input: AgentInput, event: TaskStatusUpdateEvent
344
+ def _handle_message_response(
345
+ self, agent_input: AgentInput, message: Message
340
346
  ) -> Optional[AgentOutput]:
341
347
  structlogger.debug(
342
- "a2a_agent.run_streaming_agent.task_status_update_received",
343
- event_info="Received task status update from A2A",
348
+ "a2a_agent.run.message_received",
349
+ event_info="Received message from A2A",
344
350
  agent_name=self._name,
345
- task_status_update_event=event,
346
- )
347
- agent_output = self._handle_task_status(
348
- agent_input=agent_input,
349
- context_id=event.context_id,
350
- task_id=event.task_id,
351
- task_status=event.status,
351
+ message=message,
352
352
  )
353
- return agent_output
353
+ metadata = agent_input.metadata or {}
354
+ metadata[A2A_AGENT_CONTEXT_ID_KEY] = message.context_id
354
355
 
355
- def _handle_task_artifact_update_event(
356
- self, agent_input: AgentInput, event: TaskArtifactUpdateEvent
357
- ) -> AgentOutput:
358
- structlogger.debug(
359
- "a2a_agent.run_streaming_agent.task_artifact_update_received",
360
- event_info="Received task artifact update from A2A",
361
- agent_name=self._name,
362
- task_artifact_update_event=event,
363
- )
364
356
  return AgentOutput(
365
357
  id=agent_input.id,
366
- status=AgentStatus.COMPLETED,
367
- response_message=self._generate_response_message_from_parts(
368
- event.artifact.parts
369
- ),
370
- tool_results=self._generate_tool_results_from_parts(
371
- agent_input, event.artifact.parts
372
- ),
358
+ status=AgentStatus.INPUT_REQUIRED,
359
+ response_message=self._generate_response_message_from_parts(message.parts),
360
+ metadata=metadata,
373
361
  )
374
362
 
375
363
  def _handle_unexpected_response_type(
376
364
  self, agent_input: AgentInput, response_result: Any
377
365
  ) -> AgentOutput:
378
366
  structlogger.error(
379
- "a2a_agent.run_streaming_agent.unexpected_response_type",
367
+ "a2a_agent.run.unexpected_response_type",
380
368
  event_info="Received unexpected response type from A2A server "
381
369
  "during streaming",
382
370
  agent_name=self._name,
@@ -388,29 +376,26 @@ class A2AAgent(AgentProtocol):
388
376
  error_message=f"Unexpected response type: {type(response_result)}",
389
377
  )
390
378
 
391
- def _handle_task_status(
379
+ def _handle_task(
392
380
  self,
393
381
  agent_input: AgentInput,
394
- context_id: str,
395
- task_id: str,
396
- task_status: TaskStatus,
397
- metadata: Optional[Dict[str, Any]] = None,
382
+ task: Task,
398
383
  ) -> Optional[AgentOutput]:
399
384
  """If the task status is terminal (i.e., completed, failed, etc.),
400
385
  return an AgentOutput.
401
386
  If the task is still in progress (i.e., submitted, working), return None,
402
387
  so that the streaming or pooling agent can continue to wait for updates.
403
388
  """
404
- state = task_status.state
389
+ state = task.status.state
405
390
 
406
- metadata = metadata or {}
407
- metadata[A2A_AGENT_CONTEXT_ID_KEY] = context_id
408
- metadata[A2A_AGENT_TASK_ID_KEY] = task_id
391
+ metadata = agent_input.metadata or {}
392
+ metadata[A2A_AGENT_CONTEXT_ID_KEY] = task.context_id
393
+ metadata[A2A_AGENT_TASK_ID_KEY] = task.id
409
394
 
410
395
  if state == TaskState.input_required:
411
396
  response_message = (
412
- self._generate_response_message_from_parts(task_status.message.parts)
413
- if task_status.message
397
+ self._generate_response_message_from_parts(task.status.message.parts)
398
+ if task.status.message
414
399
  else ""
415
400
  ) # This should not happen, but as type of message property
416
401
  # is optional, so we need to handle it
@@ -421,16 +406,19 @@ class A2AAgent(AgentProtocol):
421
406
  metadata=metadata,
422
407
  )
423
408
  elif state == TaskState.completed:
424
- response_message = (
425
- self._generate_response_message_from_parts(task_status.message.parts)
426
- if task_status.message
427
- else ""
428
- ) # This should not happen, but as type of message property
429
- # is optional, so we need to handle it
409
+ response_message = self._generate_completed_response_message(task)
410
+ structured_results = (
411
+ self._generate_structured_results_from_artifacts(
412
+ agent_input, task.artifacts
413
+ )
414
+ if task.artifacts
415
+ else None
416
+ )
430
417
  return AgentOutput(
431
418
  id=agent_input.id,
432
419
  status=AgentStatus.COMPLETED,
433
420
  response_message=response_message,
421
+ structured_results=structured_results,
434
422
  metadata=metadata,
435
423
  )
436
424
  elif (
@@ -469,7 +457,7 @@ class A2AAgent(AgentProtocol):
469
457
  )
470
458
 
471
459
  @staticmethod
472
- def _prepare_message_send_params(agent_input: AgentInput) -> MessageSendParams:
460
+ def _prepare_message(agent_input: AgentInput) -> Message:
473
461
  parts: List[Part] = []
474
462
  if agent_input.metadata and A2A_AGENT_CONTEXT_ID_KEY in agent_input.metadata:
475
463
  # Agent knows the conversation history already, send the last
@@ -497,17 +485,94 @@ class A2AAgent(AgentProtocol):
497
485
  task_id=agent_input.metadata.get(A2A_AGENT_TASK_ID_KEY, None),
498
486
  )
499
487
  structlogger.debug(
500
- "a2a_agent._prepare_message_send_params",
488
+ "a2a_agent.prepare_message",
501
489
  event_info="Prepared message to send to A2A server",
502
490
  agent_name=agent_input.id,
503
491
  message=agent_message,
504
492
  )
505
- return MessageSendParams(
506
- message=agent_message,
507
- configuration=MessageSendConfiguration(
508
- accepted_output_modes=["text", "text/plain", "application/json"],
509
- ),
493
+ return agent_message
494
+
495
+ async def _pool_task_until_terminal(
496
+ self,
497
+ agent_input: AgentInput,
498
+ task_id: str,
499
+ max_wait: int,
500
+ initial_delay: float,
501
+ max_delay: int,
502
+ ) -> AgentOutput:
503
+ """Poll the task status until it reaches a terminal state or times out."""
504
+ if not self._client:
505
+ structlogger.error(
506
+ "a2a_agent.pool_task_until_terminal.error",
507
+ event_info="A2A client is not initialized. Call connect() first.",
508
+ )
509
+ return AgentOutput(
510
+ id=agent_input.id,
511
+ status=AgentStatus.FATAL_ERROR,
512
+ error_message="Client not initialized",
513
+ )
514
+
515
+ structlogger.debug(
516
+ "a2a_agent.pool_task_until_terminal.start",
517
+ event_info="Start polling task from A2A server",
518
+ agent_name=self._name,
519
+ task_id=task_id,
520
+ max_wait=max_wait,
521
+ initial_delay=initial_delay,
522
+ max_delay=max_delay,
510
523
  )
524
+ start_time = time.monotonic()
525
+ delay = initial_delay
526
+
527
+ while True:
528
+ try:
529
+ task = await self._client.get_task(TaskQueryParams(id=task_id))
530
+ agent_output = self._handle_task(agent_input=agent_input, task=task)
531
+ if agent_output is not None:
532
+ # Reached a terminal state, return the output
533
+ return agent_output
534
+
535
+ elapsed = time.monotonic() - start_time
536
+ if elapsed >= max_wait:
537
+ structlogger.debug(
538
+ "a2a_agent.pool_task_until_terminal.timeout",
539
+ event_info="Polling task from A2A server timed out",
540
+ agent_name=self._name,
541
+ task_id=task_id,
542
+ elapsed=elapsed,
543
+ max_wait=max_wait,
544
+ )
545
+ return AgentOutput(
546
+ id=agent_input.id,
547
+ status=AgentStatus.FATAL_ERROR,
548
+ error_message="Polling timed out",
549
+ )
550
+
551
+ structlogger.error(
552
+ "a2a_agent.pool_task_until_terminal.waiting",
553
+ event_info="Task not in terminal state yet, waiting to poll again",
554
+ delay=delay,
555
+ agent_name=self._name,
556
+ task_id=task_id,
557
+ elapsed=elapsed,
558
+ max_wait=max_wait,
559
+ )
560
+ await asyncio.sleep(delay)
561
+ # Exponential backoff with cap
562
+ delay = min(delay * 2, max_delay)
563
+
564
+ except A2AClientError as exception:
565
+ structlogger.error(
566
+ "a2a_agent.pool_task_until_terminal.error",
567
+ event_info="Error during polling task from A2A server",
568
+ agent_name=self._name,
569
+ error=str(exception),
570
+ )
571
+ return AgentOutput(
572
+ id=agent_input.id,
573
+ status=AgentStatus.FATAL_ERROR,
574
+ error_message=f"Polling error: {exception!s}",
575
+ )
511
576
 
512
577
  @staticmethod
513
578
  def _generate_response_message_from_parts(parts: Optional[List[Part]]) -> str:
@@ -519,7 +584,7 @@ class A2AAgent(AgentProtocol):
519
584
  if isinstance(part.root, TextPart):
520
585
  result += part.root.text + "\n"
521
586
  elif isinstance(part.root, DataPart):
522
- # DataPart results will be returned as a pert of the tool results,
587
+ # DataPart results will be returned as a part of the structured results,
523
588
  # we don't need to include it in the response message
524
589
  continue
525
590
  elif isinstance(part.root, FilePart) and isinstance(
@@ -536,29 +601,66 @@ class A2AAgent(AgentProtocol):
536
601
  return result.strip()
537
602
 
538
603
  @staticmethod
539
- def _generate_tool_results_from_parts(
540
- agent_input: AgentInput, parts: List[Part]
541
- ) -> Optional[List[List[Dict[str, Any]]]]:
542
- tool_results_of_current_iteration: List[Dict[str, Any]] = []
543
- for i, part in enumerate(parts):
544
- if (
545
- isinstance(part.root, DataPart)
546
- and part.root.data
547
- and len(part.root.data) > 0
548
- ):
549
- # There might be multiple DataParts in the response,
550
- # we will treat each of them as a separate tool result.
551
- # The tool name will be the agent ID + index of the part.
552
- tool_results_of_current_iteration.append(
553
- {"tool_name": f"{agent_input.id}_{i}", "result": part.root.data}
604
+ def _generate_completed_response_message(task: Task) -> str:
605
+ """Generate a response message for a completed task.
606
+ In case of completed tasks, the final message might be in
607
+ the task status message or in the artifacts (or both).
608
+ """
609
+ result = ""
610
+ if task.status.message:
611
+ result += (
612
+ A2AAgent._generate_response_message_from_parts(
613
+ task.status.message.parts
614
+ )
615
+ + "\n"
616
+ )
617
+ if task.artifacts:
618
+ for artifact in task.artifacts:
619
+ result += (
620
+ A2AAgent._generate_response_message_from_parts(artifact.parts)
621
+ + "\n"
554
622
  )
623
+ return result.strip()
555
624
 
556
- previous_tool_results: List[List[Dict[str, Any]]] = (
557
- agent_input.metadata.get(AGENT_METADATA_TOOL_RESULTS_KEY, []) or []
625
+ @staticmethod
626
+ def _generate_structured_results_from_artifacts(
627
+ agent_input: AgentInput, artifacts: List[Artifact]
628
+ ) -> Optional[List[List[Dict[str, Any]]]]:
629
+ structured_results_of_current_iteration: List[Dict[str, Any]] = []
630
+ # There might be multiple artifacts in the response, each of them might
631
+ # contain multiple parts. We will treat each DataPart in each artifact
632
+ # as a separate tool result. The tool name will be the agent ID + index
633
+ # of the artifact + index of the part.
634
+ # E.g., foo_0_1, foo_0_2, foo_1_0, etc.
635
+ for artifact_index, artifact in enumerate(artifacts):
636
+ for part_index, part in enumerate(artifact.parts):
637
+ if isinstance(part.root, DataPart) and len(part.root.data) > 0:
638
+ structured_result = {
639
+ "name": f"{agent_input.id}_{artifact_index}_{part_index}",
640
+ "type": "data",
641
+ "result": part.root.data,
642
+ }
643
+ structured_results_of_current_iteration.append(structured_result)
644
+ elif isinstance(part.root, FilePart) and isinstance(
645
+ part.root.file, FileWithUri
646
+ ):
647
+ structured_result = {
648
+ "name": f"{agent_input.id}_{artifact_index}_{part_index}",
649
+ "type": "file",
650
+ "result ": {
651
+ "uri": part.root.file.uri,
652
+ "name": part.root.file.name,
653
+ "mime_type": part.root.file.mime_type,
654
+ },
655
+ }
656
+ structured_results_of_current_iteration.append(structured_result)
657
+
658
+ previous_structured_results: List[List[Dict[str, Any]]] = (
659
+ agent_input.metadata.get(AGENT_METADATA_STRUCTURED_RESULTS_KEY, []) or []
558
660
  )
559
- previous_tool_results.append(tool_results_of_current_iteration)
661
+ previous_structured_results.append(structured_results_of_current_iteration)
560
662
 
561
- return previous_tool_results
663
+ return previous_structured_results
562
664
 
563
665
  @staticmethod
564
666
  def _load_agent_card_from_file(agent_card_path: str) -> AgentCard:
@@ -566,42 +668,24 @@ class A2AAgent(AgentProtocol):
566
668
  try:
567
669
  with open(os.path.abspath(agent_card_path), "r") as f:
568
670
  card_data = json.load(f)
671
+ return AgentCard.model_validate(card_data)
569
672
 
570
- skills = [
571
- AgentSkill(
572
- id=skill_data["id"],
573
- name=skill_data["name"],
574
- description=skill_data["description"],
575
- tags=skill_data.get("tags", []),
576
- examples=skill_data.get("examples", []),
577
- )
578
- for skill_data in card_data.get("skills", [])
579
- ]
580
-
581
- return AgentCard(
582
- name=card_data["name"],
583
- description=card_data["description"],
584
- url=card_data["url"],
585
- version=card_data.get("version", "1.0.0"),
586
- default_input_modes=card_data.get(
587
- "defaultInputModes", ["text", "text/plain"]
588
- ),
589
- default_output_modes=card_data.get(
590
- "defaultOutputModes", ["text", "text/plain", "application/json"]
591
- ),
592
- capabilities=AgentCapabilities(
593
- streaming=card_data.get("capabilities", {}).get("streaming", True)
594
- ),
595
- skills=skills,
596
- )
597
- except FileNotFoundError:
598
- raise FileNotFoundError(f"Agent card file not found: {agent_card_path}")
673
+ except FileNotFoundError as e:
674
+ raise AgentInitializationException(
675
+ f"Agent card file not found: {agent_card_path}"
676
+ ) from e
677
+ except (IOError, PermissionError) as e:
678
+ raise AgentInitializationException(
679
+ f"Error reading agent card file {agent_card_path}: {e}"
680
+ ) from e
599
681
  except json.JSONDecodeError as e:
600
- raise ValueError(f"Invalid JSON in agent card file {agent_card_path}: {e}")
601
- except KeyError as e:
602
- raise ValueError(
603
- f"Missing required field in agent card {agent_card_path}: {e}"
604
- )
682
+ raise AgentInitializationException(
683
+ f"Invalid JSON in agent card file {agent_card_path}: {e}"
684
+ ) from e
685
+ except ValidationError as e:
686
+ raise AgentInitializationException(
687
+ f"Failed to load agent card from {agent_card_path}: {e}"
688
+ ) from e
605
689
 
606
690
  @staticmethod
607
691
  async def _resolve_agent_card_with_retry(
@@ -660,3 +744,77 @@ class A2AAgent(AgentProtocol):
660
744
  f"Failed to resolve agent card from {agent_card_path} after "
661
745
  f"{max_retries} attempts."
662
746
  )
747
+
748
+ def _init_client(self) -> Client:
749
+ factory = ClientFactory(
750
+ config=ClientConfig(
751
+ httpx_client=httpx.AsyncClient(timeout=self._timeout),
752
+ streaming=True,
753
+ supported_transports=[
754
+ TransportProtocol.jsonrpc,
755
+ TransportProtocol.http_json,
756
+ TransportProtocol.grpc,
757
+ ],
758
+ accepted_output_modes=self.__SUPPORTED_OUTPUT_MODES,
759
+ )
760
+ )
761
+ return factory.create(self.agent_card)
762
+
763
+ async def _perform_health_check(self) -> None:
764
+ if not self._client or not self.agent_card:
765
+ structlogger.error(
766
+ "a2a_agent.health_check.error",
767
+ event_info="A2A client is not initialized. Call connect() first.",
768
+ )
769
+ raise AgentInitializationException("Client not initialized")
770
+
771
+ try:
772
+ test_message = Message(
773
+ role=Role.user,
774
+ parts=[Part(root=TextPart(text="hello"))],
775
+ message_id=str(uuid.uuid4()),
776
+ )
777
+ async for event in self._client.send_message(test_message):
778
+ if (
779
+ isinstance(event, Message)
780
+ or isinstance(event, tuple)
781
+ and len(event) == 2
782
+ and isinstance(event[0], Task)
783
+ ):
784
+ # We got a valid response, health check succeeded
785
+ return
786
+
787
+ event_info = "Unexpected response type during health check"
788
+ structlogger.error(
789
+ "a2a_agent.health_check.unexpected_response",
790
+ event_info=event_info,
791
+ agent_name=self._name,
792
+ response=event,
793
+ url=str(self.agent_card.url),
794
+ )
795
+ raise AgentInitializationException(f"{event_info}: {event}")
796
+ # If the loop completes with no return, no events were received
797
+ event_info = (
798
+ f"Health check failed for A2A agent '{self._name}' "
799
+ f"at {self.agent_card.url}: no events received"
800
+ )
801
+ structlogger.error(
802
+ "a2a_agent.health_check.no_events",
803
+ event_info=event_info,
804
+ agent_name=self._name,
805
+ url=str(self.agent_card.url),
806
+ )
807
+ raise AgentInitializationException(event_info)
808
+ except Exception as exception:
809
+ event_info = (
810
+ f"Health check failed for A2A agent '{self._name}' at "
811
+ f"{self.agent_card.url}: {exception!s}"
812
+ )
813
+ structlogger.error(
814
+ "a2a_agent.health_check.failed",
815
+ event_info=event_info,
816
+ agent_name=self._name,
817
+ error=str(exception),
818
+ url=str(self.agent_card.url),
819
+ )
820
+ raise AgentInitializationException(event_info) from exception