rasa-pro 3.14.0.dev20250922__py3-none-any.whl → 3.14.0rc1__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 (290) hide show
  1. rasa/__main__.py +15 -3
  2. rasa/agents/__init__.py +0 -0
  3. rasa/agents/agent_factory.py +122 -0
  4. rasa/agents/agent_manager.py +211 -0
  5. rasa/agents/constants.py +43 -0
  6. rasa/agents/core/__init__.py +0 -0
  7. rasa/agents/core/agent_protocol.py +107 -0
  8. rasa/agents/core/types.py +81 -0
  9. rasa/agents/exceptions.py +38 -0
  10. rasa/agents/protocol/__init__.py +5 -0
  11. rasa/agents/protocol/a2a/__init__.py +0 -0
  12. rasa/agents/protocol/a2a/a2a_agent.py +879 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
  15. rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
  16. rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
  17. rasa/agents/schemas/__init__.py +13 -0
  18. rasa/agents/schemas/agent_input.py +38 -0
  19. rasa/agents/schemas/agent_output.py +26 -0
  20. rasa/agents/schemas/agent_tool_result.py +65 -0
  21. rasa/agents/schemas/agent_tool_schema.py +186 -0
  22. rasa/agents/templates/__init__.py +0 -0
  23. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
  24. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
  25. rasa/agents/utils.py +206 -0
  26. rasa/agents/validation.py +485 -0
  27. rasa/api.py +24 -9
  28. rasa/builder/config.py +6 -2
  29. rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
  30. rasa/builder/guardrails/constants.py +3 -0
  31. rasa/builder/guardrails/models.py +45 -10
  32. rasa/builder/guardrails/policy_checker.py +324 -0
  33. rasa/builder/guardrails/utils.py +42 -276
  34. rasa/builder/llm_service.py +32 -5
  35. rasa/builder/models.py +1 -0
  36. rasa/builder/project_generator.py +6 -1
  37. rasa/builder/service.py +16 -13
  38. rasa/builder/training_service.py +18 -24
  39. rasa/builder/validation_service.py +1 -1
  40. rasa/cli/arguments/default_arguments.py +12 -0
  41. rasa/cli/arguments/run.py +2 -0
  42. rasa/cli/arguments/train.py +2 -0
  43. rasa/cli/data.py +10 -8
  44. rasa/cli/dialogue_understanding_test.py +10 -7
  45. rasa/cli/e2e_test.py +9 -6
  46. rasa/cli/evaluate.py +4 -2
  47. rasa/cli/export.py +5 -2
  48. rasa/cli/inspect.py +8 -4
  49. rasa/cli/interactive.py +5 -4
  50. rasa/cli/llm_fine_tuning.py +11 -6
  51. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  52. rasa/cli/run.py +12 -10
  53. rasa/cli/scaffold.py +4 -4
  54. rasa/cli/shell.py +9 -5
  55. rasa/cli/studio/studio.py +1 -1
  56. rasa/cli/test.py +34 -14
  57. rasa/cli/train.py +41 -28
  58. rasa/cli/utils.py +1 -393
  59. rasa/cli/validation/__init__.py +0 -0
  60. rasa/cli/validation/bot_config.py +223 -0
  61. rasa/cli/validation/config_path_validation.py +257 -0
  62. rasa/cli/x.py +8 -4
  63. rasa/constants.py +7 -1
  64. rasa/core/actions/action.py +51 -10
  65. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  66. rasa/core/agent.py +19 -2
  67. rasa/core/available_agents.py +229 -0
  68. rasa/core/channels/__init__.py +82 -35
  69. rasa/core/channels/development_inspector.py +3 -3
  70. rasa/core/channels/inspector/README.md +25 -13
  71. rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  75. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  78. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  84. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  90. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
  94. rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
  95. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  96. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  97. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  98. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  99. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  100. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  101. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
  102. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  103. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  104. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
  105. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
  106. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  107. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  108. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  109. rasa/core/channels/inspector/dist/index.html +1 -1
  110. rasa/core/channels/inspector/package.json +18 -18
  111. rasa/core/channels/inspector/src/App.tsx +29 -4
  112. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  113. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  114. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
  115. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  116. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  117. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  118. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  119. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  120. rasa/core/channels/inspector/src/types.ts +21 -0
  121. rasa/core/channels/inspector/yarn.lock +336 -189
  122. rasa/core/channels/studio_chat.py +6 -6
  123. rasa/core/channels/telegram.py +4 -9
  124. rasa/core/channels/voice_stream/genesys.py +1 -1
  125. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  126. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
  127. rasa/core/channels/voice_stream/voice_channel.py +3 -0
  128. rasa/core/config/__init__.py +0 -0
  129. rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
  130. rasa/core/config/configuration.py +260 -0
  131. rasa/core/config/credentials.py +19 -0
  132. rasa/core/config/message_procesing_config.py +34 -0
  133. rasa/core/constants.py +4 -0
  134. rasa/core/policies/enterprise_search_policy.py +5 -3
  135. rasa/core/policies/flow_policy.py +4 -4
  136. rasa/core/policies/flows/agent_executor.py +632 -0
  137. rasa/core/policies/flows/flow_executor.py +136 -75
  138. rasa/core/policies/flows/mcp_tool_executor.py +298 -0
  139. rasa/core/policies/intentless_policy.py +1 -1
  140. rasa/core/policies/ted_policy.py +20 -12
  141. rasa/core/policies/unexpected_intent_policy.py +6 -0
  142. rasa/core/processor.py +68 -44
  143. rasa/core/run.py +37 -8
  144. rasa/core/test.py +4 -0
  145. rasa/core/tracker_stores/tracker_store.py +3 -7
  146. rasa/core/train.py +1 -1
  147. rasa/core/training/interactive.py +20 -18
  148. rasa/core/training/story_conflict.py +5 -5
  149. rasa/core/utils.py +22 -23
  150. rasa/dialogue_understanding/commands/__init__.py +8 -0
  151. rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
  152. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  153. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  154. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  155. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  156. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  157. rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
  158. rasa/dialogue_understanding/commands/utils.py +124 -2
  159. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  160. rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
  161. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  162. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  163. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  164. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  165. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  166. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  167. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  168. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  169. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  170. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  171. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  172. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  173. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
  174. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  175. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  176. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  177. rasa/dialogue_understanding/stack/utils.py +57 -3
  178. rasa/dialogue_understanding/utils.py +24 -4
  179. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  180. rasa/e2e_test/e2e_test_runner.py +13 -3
  181. rasa/engine/caching.py +2 -2
  182. rasa/engine/constants.py +1 -1
  183. rasa/engine/recipes/default_components.py +138 -49
  184. rasa/engine/recipes/default_recipe.py +108 -11
  185. rasa/engine/runner/dask.py +8 -5
  186. rasa/engine/validation.py +19 -6
  187. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  188. rasa/hooks.py +5 -5
  189. rasa/llm_fine_tuning/utils.py +2 -2
  190. rasa/model_training.py +60 -47
  191. rasa/nlu/classifiers/diet_classifier.py +198 -98
  192. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  193. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  194. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  195. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  196. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  197. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  198. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  199. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  200. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  201. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  202. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  203. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  204. rasa/nlu/selectors/response_selector.py +10 -2
  205. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  206. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  207. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  208. rasa/nlu/utils/mitie_utils.py +3 -0
  209. rasa/nlu/utils/spacy_utils.py +3 -2
  210. rasa/plugin.py +8 -8
  211. rasa/privacy/privacy_manager.py +12 -3
  212. rasa/server.py +15 -3
  213. rasa/shared/agents/__init__.py +0 -0
  214. rasa/shared/agents/auth/__init__.py +0 -0
  215. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  216. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  217. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  218. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  219. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  220. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  221. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
  222. rasa/shared/agents/auth/constants.py +12 -0
  223. rasa/shared/agents/auth/types.py +12 -0
  224. rasa/shared/agents/utils.py +35 -0
  225. rasa/shared/constants.py +8 -0
  226. rasa/shared/core/constants.py +16 -1
  227. rasa/shared/core/domain.py +0 -7
  228. rasa/shared/core/events.py +327 -0
  229. rasa/shared/core/flows/constants.py +5 -0
  230. rasa/shared/core/flows/flows_list.py +21 -5
  231. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  232. rasa/shared/core/flows/steps/call.py +49 -5
  233. rasa/shared/core/flows/steps/collect.py +98 -13
  234. rasa/shared/core/flows/validation.py +372 -8
  235. rasa/shared/core/flows/yaml_flows_io.py +3 -2
  236. rasa/shared/core/slots.py +2 -2
  237. rasa/shared/core/trackers.py +5 -2
  238. rasa/shared/exceptions.py +16 -0
  239. rasa/shared/importers/rasa.py +1 -1
  240. rasa/shared/importers/utils.py +9 -3
  241. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  242. rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
  243. rasa/shared/providers/llm/llm_client.py +7 -3
  244. rasa/shared/providers/llm/llm_response.py +66 -0
  245. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  246. rasa/shared/utils/common.py +24 -0
  247. rasa/shared/utils/health_check/health_check.py +7 -3
  248. rasa/shared/utils/llm.py +39 -16
  249. rasa/shared/utils/mcp/__init__.py +0 -0
  250. rasa/shared/utils/mcp/server_connection.py +247 -0
  251. rasa/shared/utils/mcp/utils.py +20 -0
  252. rasa/shared/utils/schemas/events.py +42 -0
  253. rasa/shared/utils/yaml.py +3 -1
  254. rasa/studio/pull/pull.py +3 -2
  255. rasa/studio/train.py +8 -7
  256. rasa/studio/upload.py +3 -6
  257. rasa/telemetry.py +69 -5
  258. rasa/tracing/config.py +45 -12
  259. rasa/tracing/constants.py +14 -0
  260. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  261. rasa/tracing/instrumentation/instrumentation.py +626 -21
  262. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  263. rasa/tracing/instrumentation/metrics.py +32 -0
  264. rasa/tracing/metric_instrument_provider.py +68 -0
  265. rasa/utils/common.py +92 -1
  266. rasa/utils/endpoints.py +11 -2
  267. rasa/utils/log_utils.py +96 -5
  268. rasa/utils/ml_utils.py +1 -1
  269. rasa/utils/tensorflow/__init__.py +7 -0
  270. rasa/utils/tensorflow/callback.py +136 -101
  271. rasa/utils/tensorflow/crf.py +1 -1
  272. rasa/utils/tensorflow/data_generator.py +21 -8
  273. rasa/utils/tensorflow/layers.py +21 -11
  274. rasa/utils/tensorflow/metrics.py +7 -3
  275. rasa/utils/tensorflow/models.py +56 -8
  276. rasa/utils/tensorflow/rasa_layers.py +8 -6
  277. rasa/utils/tensorflow/transformer.py +2 -3
  278. rasa/utils/train_utils.py +54 -24
  279. rasa/validator.py +5 -5
  280. rasa/version.py +1 -1
  281. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/METADATA +46 -41
  282. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/RECORD +285 -226
  283. rasa/builder/scrape_rasa_docs.py +0 -97
  284. rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
  285. rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
  286. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
  287. rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
  288. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/NOTICE +0 -0
  289. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/WHEEL +0 -0
  290. {rasa_pro-3.14.0.dev20250922.dist-info → rasa_pro-3.14.0rc1.dist-info}/entry_points.txt +0 -0
rasa/__main__.py CHANGED
@@ -1,4 +1,7 @@
1
1
  import argparse
2
+
3
+ # Check TensorFlow availability without importing the module
4
+ import importlib.util
2
5
  import os
3
6
  import platform
4
7
  import sys
@@ -10,7 +13,6 @@ from rasa_sdk import __version__ as rasa_sdk_version
10
13
  import rasa.telemetry
11
14
  import rasa.utils.io
12
15
  import rasa.utils.licensing
13
- import rasa.utils.tensorflow.environment as tf_env
14
16
  from rasa import version
15
17
  from rasa.cli import (
16
18
  data,
@@ -40,6 +42,14 @@ from rasa.shared.exceptions import RasaException
40
42
  from rasa.utils.common import configure_logging_and_warnings
41
43
  from rasa.utils.log_utils import configure_structlog
42
44
 
45
+ TENSORFLOW_AVAILABLE = importlib.util.find_spec("tensorflow") is not None
46
+
47
+ # Only import TensorFlow modules if TensorFlow is available
48
+ if TENSORFLOW_AVAILABLE:
49
+ import rasa.utils.tensorflow.environment as tf_env
50
+ else:
51
+ tf_env = None # type: ignore[assignment]
52
+
43
53
  structlogger = structlog.get_logger()
44
54
 
45
55
 
@@ -123,8 +133,10 @@ def main(raw_arguments: Optional[List[str]] = None) -> None:
123
133
  rasa.utils.io.configure_colored_logging(log_level)
124
134
  configure_structlog(log_level)
125
135
 
126
- tf_env.setup_tf_environment()
127
- tf_env.check_deterministic_ops()
136
+ # Only setup TensorFlow environment if TensorFlow is available
137
+ if TENSORFLOW_AVAILABLE and tf_env is not None:
138
+ tf_env.setup_tf_environment()
139
+ tf_env.check_deterministic_ops()
128
140
 
129
141
  # insert current path in syspath so custom modules are found
130
142
  sys.path.insert(1, os.getcwd())
File without changes
@@ -0,0 +1,122 @@
1
+ from typing import Any, ClassVar, Dict, List, Type
2
+
3
+ import structlog
4
+
5
+ from rasa.agents.core.agent_protocol import AgentProtocol
6
+ from rasa.agents.core.types import ProtocolType
7
+ from rasa.agents.protocol import A2AAgent, MCPOpenAgent, MCPTaskAgent
8
+ from rasa.core.available_agents import AgentConfig
9
+ from rasa.shared.utils.common import class_from_module_path
10
+
11
+ structlogger = structlog.get_logger()
12
+
13
+
14
+ class AgentFactory:
15
+ """Factory for creating agent instances based on the protocol type."""
16
+
17
+ _protocols: ClassVar[Dict[ProtocolType, Type[AgentProtocol]]] = {
18
+ ProtocolType.A2A: A2AAgent,
19
+ ProtocolType.MCP_OPEN: MCPOpenAgent,
20
+ ProtocolType.MCP_TASK: MCPTaskAgent,
21
+ }
22
+
23
+ @classmethod
24
+ def create_client(
25
+ cls, protocol_type: ProtocolType, config: AgentConfig
26
+ ) -> AgentProtocol:
27
+ """Create an agent instance based on the protocol type.
28
+
29
+ Args:
30
+ protocol_type: The protocol type of the agent.
31
+ config: The configuration for the agent as an AgentConfig object.
32
+
33
+ Returns:
34
+ An instance of the agent.
35
+ """
36
+ # If the agent is a custom agent, we need to create it from the module
37
+ if config.configuration and config.configuration.module:
38
+ agent_class: Type[AgentProtocol] = class_from_module_path(
39
+ config.configuration.module
40
+ )
41
+ if not cls._is_valid_custom_agent(agent_class, protocol_type):
42
+ raise ValueError(
43
+ f"Agent class `{agent_class}` does not subclass the "
44
+ f"{cls._get_agent_class_from_protocol(protocol_type).__name__} "
45
+ f"agent class."
46
+ )
47
+ structlogger.debug(
48
+ "agent_factory.create_client.custom_agent",
49
+ event_info=(
50
+ f"Initializing `{agent_class.__name__}` for agent "
51
+ f"`{config.agent.name}` with protocol `{protocol_type.value}`"
52
+ ),
53
+ agent_name=config.agent.name,
54
+ protocol_type=protocol_type.value,
55
+ agent_class=agent_class.__name__,
56
+ )
57
+ return agent_class.from_config(config)
58
+
59
+ # If the agent is a built-in agent, we need to create it from the protocol class
60
+ protocol_class = cls._get_agent_class_from_protocol(protocol_type)
61
+ if protocol_class is None:
62
+ raise ValueError(
63
+ f"Unsupported protocol: {protocol_type}. "
64
+ f"Supported protocols: {cls.get_supported_protocols()}"
65
+ )
66
+
67
+ structlogger.debug(
68
+ "agent_factory.create_client",
69
+ event_info=(
70
+ f"Initializing `{protocol_class.__name__}` for agent "
71
+ f"`{config.agent.name}` with protocol `{protocol_type.value}`"
72
+ ),
73
+ agent_name=config.agent.name,
74
+ protocol_type=protocol_type.value,
75
+ agent_class=protocol_class.__name__,
76
+ )
77
+ return protocol_class.from_config(config)
78
+
79
+ @classmethod
80
+ def register_protocol(
81
+ cls, protocol_type: ProtocolType, protocol_class: Type[AgentProtocol]
82
+ ) -> None:
83
+ """Register new protocol implementation.
84
+
85
+ Args:
86
+ protocol_type: The protocol type of the agent.
87
+ protocol_class: The class that implements the protocol.
88
+ """
89
+ if cls.is_protocol_supported(protocol_type):
90
+ raise ValueError(f"Protocol {protocol_type.name} already registered.")
91
+ cls._protocols[protocol_type] = protocol_class
92
+
93
+ @classmethod
94
+ def get_supported_protocols(cls) -> List[ProtocolType]:
95
+ """Get all supported protocol types."""
96
+ return list(cls._protocols.keys())
97
+
98
+ @classmethod
99
+ def _get_agent_class_from_protocol(
100
+ cls, protocol_type: ProtocolType
101
+ ) -> Type[AgentProtocol]:
102
+ """Get the class that implements the protocol."""
103
+ if not cls.is_protocol_supported(protocol_type):
104
+ raise ValueError(
105
+ f"Unsupported protocol: {protocol_type}. "
106
+ f"Supported protocols: {cls.get_supported_protocols()}"
107
+ )
108
+ return cls._protocols[protocol_type]
109
+
110
+ @classmethod
111
+ def is_protocol_supported(cls, protocol_type: ProtocolType) -> bool:
112
+ """Check if the protocol is supported."""
113
+ return protocol_type in cls._protocols
114
+
115
+ @classmethod
116
+ def _is_valid_custom_agent(
117
+ cls, agent_class: Any, protocol_type: ProtocolType
118
+ ) -> bool:
119
+ """Check if the agent class is valid."""
120
+ return issubclass(
121
+ agent_class, cls._get_agent_class_from_protocol(protocol_type)
122
+ )
@@ -0,0 +1,211 @@
1
+ from typing import ClassVar, Dict
2
+
3
+ import structlog
4
+
5
+ from rasa.agents.agent_factory import AgentFactory
6
+ from rasa.agents.core.agent_protocol import AgentProtocol
7
+ from rasa.agents.core.types import AgentIdentifier, ProtocolType
8
+ from rasa.agents.schemas import AgentInput, AgentOutput
9
+ from rasa.core.available_agents import AgentConfig
10
+ from rasa.shared.agents.utils import make_agent_identifier
11
+ from rasa.shared.exceptions import AgentInitializationException
12
+ from rasa.utils.singleton import Singleton
13
+
14
+ structlogger = structlog.get_logger()
15
+
16
+
17
+ class AgentManager(metaclass=Singleton):
18
+ """High-level agent management with protocol abstraction"""
19
+
20
+ agents: ClassVar[Dict[AgentIdentifier, AgentProtocol]] = {}
21
+
22
+ def _add_agent(
23
+ self, agent_identifier: AgentIdentifier, agent: AgentProtocol
24
+ ) -> None:
25
+ """Add an agent to the manager.
26
+
27
+ Args:
28
+ agent_identifier: The identifier of the agent.
29
+ agent: The agent to add.
30
+ """
31
+ if agent_identifier in self.agents:
32
+ raise ValueError(f"Agent {agent_identifier} already exists")
33
+ self.agents[agent_identifier] = agent
34
+
35
+ def _remove_agent(self, agent_identifier: AgentIdentifier) -> None:
36
+ """Remove an agent from the manager.
37
+
38
+ Args:
39
+ agent_identifier: The identifier of the agent.
40
+
41
+ Raises:
42
+ ValueError: If the agent is not connected.
43
+ """
44
+ if agent_identifier not in self.agents:
45
+ raise ValueError(f"Agent {agent_identifier} is not available")
46
+ del self.agents[agent_identifier]
47
+
48
+ def get_agent(self, agent_name: str, protocol_type: ProtocolType) -> AgentProtocol:
49
+ """Retrieve connected agent instance.
50
+
51
+ Args:
52
+ agent_name: The name of the agent.
53
+ protocol_type: The protocol type of the agent.
54
+
55
+ Returns:
56
+ The agent.
57
+
58
+ Raises:
59
+ ValueError: If the agent is not connected.
60
+ """
61
+ agent_identifier = make_agent_identifier(agent_name, protocol_type)
62
+ if agent_identifier not in self.agents:
63
+ raise ValueError(f"Agent {agent_identifier} is not available")
64
+ return self.agents[agent_identifier]
65
+
66
+ async def connect_agent(
67
+ self, agent_name: str, protocol_type: ProtocolType, config: AgentConfig
68
+ ) -> None:
69
+ """Connect to agent using specified protocol, load the default resources
70
+ and persist the agent to the manager in a ready-to-use state so that
71
+ it can be used immediately to send messages to the agent.
72
+
73
+ Args:
74
+ agent_name: The name of the agent.
75
+ protocol_type: The protocol type of the agent.
76
+ config: The configuration for the agent as an AgentConfig object.
77
+
78
+ Raises:
79
+ ConnectionError: If the agent connection fails.
80
+ """
81
+ # Add the agent to the manager
82
+ agent_identifier = make_agent_identifier(agent_name, protocol_type)
83
+ if agent_identifier in self.agents:
84
+ structlogger.info(
85
+ "agent_manager.connect_agent.already_connected",
86
+ agent_id=str(agent_identifier),
87
+ agent_name=agent_name,
88
+ event_info=f"Agent {agent_identifier} already connected",
89
+ )
90
+ return
91
+ try:
92
+ # Create the agent client
93
+ client = AgentFactory.create_client(protocol_type, config)
94
+
95
+ # Connect the agent client
96
+ await client.connect()
97
+
98
+ self._add_agent(agent_identifier, client)
99
+ structlogger.info(
100
+ "agent_manager.connect_agent.success",
101
+ agent_id=str(agent_identifier),
102
+ agent_name=agent_name,
103
+ event_info=f"Connected to agent - `{agent_identifier}` successfully",
104
+ )
105
+ except Exception as e:
106
+ event_info = f"Failed to connect agent {agent_identifier}"
107
+ structlogger.error(
108
+ "agent_manager.connect_agent.failed_to_connect",
109
+ agent_id=str(agent_identifier),
110
+ event_info=event_info,
111
+ )
112
+ raise AgentInitializationException(e) from e
113
+
114
+ async def run_agent(
115
+ self, agent_name: str, protocol_type: ProtocolType, context: AgentInput
116
+ ) -> AgentOutput:
117
+ """Run an agent, send the input to the agent and return the agent response.
118
+
119
+ Args:
120
+ agent_name: The name of the agent.
121
+ protocol_type: The protocol type of the agent.
122
+ context: The input to the agent as an AgentInput object.
123
+
124
+ Returns:
125
+ The response from the agent.
126
+ """
127
+ agent = self.get_agent(agent_name, protocol_type)
128
+
129
+ structlogger.debug(
130
+ "agent_manager.run_agent.input",
131
+ event_info="Processing agent input before sending...",
132
+ agent_name=agent_name,
133
+ protocol_type=protocol_type,
134
+ )
135
+
136
+ # Process input before sending
137
+ try:
138
+ processed_input = await agent.process_input(context)
139
+ except Exception as e:
140
+ structlogger.error(
141
+ "agent_manager.run_agent.process_input_failed",
142
+ agent_name=agent_name,
143
+ protocol_type=protocol_type,
144
+ event_info=(
145
+ f"Failed to process input for agent '{agent_name}'. "
146
+ "Please check your custom implementation."
147
+ ),
148
+ error_message=str(e),
149
+ )
150
+ raise
151
+
152
+ # Send message to agent
153
+ output = await agent.run(processed_input)
154
+
155
+ structlogger.debug(
156
+ "agent_manager.run_agent.output",
157
+ event_info="Agent output received. Processing output...",
158
+ agent_name=agent_name,
159
+ protocol_type=protocol_type,
160
+ )
161
+
162
+ # Process output before returning
163
+ try:
164
+ processed_output = await agent.process_output(output)
165
+ except Exception as e:
166
+ structlogger.error(
167
+ "agent_manager.run_agent.process_output_failed",
168
+ agent_name=agent_name,
169
+ protocol_type=protocol_type,
170
+ event_info=(
171
+ f"Failed to process output for agent '{agent_name}'. "
172
+ "Please check your custom implementation."
173
+ ),
174
+ error_message=str(e),
175
+ )
176
+ raise
177
+
178
+ return processed_output
179
+
180
+ async def disconnect_agent(
181
+ self, agent_name: str, protocol_type: ProtocolType
182
+ ) -> None:
183
+ """Disconnect agent and remove from agent manager.
184
+
185
+ Args:
186
+ agent_name: The name of the agent.
187
+ protocol_type: The protocol type of the agent.
188
+
189
+ Raises:
190
+ ValueError: If the agent is not available.
191
+ ConnectionError: If the agent disconnection fails.
192
+ """
193
+ agent_identifier = make_agent_identifier(agent_name, protocol_type)
194
+ if agent_identifier not in self.agents:
195
+ raise ValueError(f"Agent {agent_identifier} is not available")
196
+ try:
197
+ await self.get_agent(agent_name, protocol_type).disconnect()
198
+ self._remove_agent(agent_identifier)
199
+ structlogger.info(
200
+ "agent_manager.disconnect_agent.success",
201
+ agent_id=str(agent_identifier),
202
+ event_info=f"Disconnected from agent - {agent_identifier} successfully",
203
+ )
204
+ except Exception as e:
205
+ event_info = f"Failed to disconnect agent {agent_identifier}"
206
+ structlogger.error(
207
+ "agent_manager.disconnect_agent.failed_to_disconnect",
208
+ agent_id=str(agent_identifier),
209
+ event_info=event_info,
210
+ )
211
+ raise ConnectionError(e)
@@ -0,0 +1,43 @@
1
+ # Agent configuration constants
2
+ AGENT_DEFAULT_MAX_RETRIES = 5
3
+ AGENT_DEFAULT_TIMEOUT_SECONDS = 30
4
+ MAX_AGENT_RETRY_DELAY_SECONDS = 5
5
+
6
+ # MCP Tool related constants (primary)
7
+ TOOL_TYPE_KEY = "type"
8
+ TOOL_NAME_KEY = "name"
9
+ TOOL_DESCRIPTION_KEY = "description"
10
+ TOOL_PARAMETERS_KEY = "parameters"
11
+ TOOL_STRICT_KEY = "strict"
12
+ TOOL_TYPE_FUNCTION_KEY = "function"
13
+ TOOL_EXECUTOR_KEY = "tool_executor"
14
+
15
+ # MCP Tool related constants (secondary)
16
+ TOOL_ADDITIONAL_PROPERTIES_KEY = "additionalProperties"
17
+ TOOL_PROPERTIES_KEY = "properties"
18
+ TOOL_REQUIRED_KEY = "required"
19
+ TOOL_PROPERTY_TYPE_KEY = "type"
20
+
21
+ # MCP Tool Anthropic format related constants
22
+ TOOL_INPUT_SCHEMA_KEY = "input_schema"
23
+
24
+ # MCP Message related constants
25
+ KEY_ROLE = "role"
26
+ KEY_CONTENT = "content"
27
+
28
+ # MCP Tool call related constants
29
+ KEY_TOOL_CALL_ID = "tool_call_id"
30
+ KEY_FUNCTION = "function"
31
+ KEY_NAME = "name"
32
+ KEY_ARGUMENTS = "arguments"
33
+ KEY_ID = "id"
34
+ KEY_TYPE = "type"
35
+ KEY_TOOL_CALLS = "tool_calls"
36
+
37
+ # Agent output metadata related constants
38
+ AGENT_METADATA_AGENT_RESPONSE_KEY = "agent_response"
39
+ AGENT_METADATA_STRUCTURED_RESULTS_KEY = "structured_results"
40
+ AGENT_METADATA_EXIT_IF_KEY = "exit_if"
41
+ # A2A-specific constants
42
+ A2A_AGENT_CONTEXT_ID_KEY = "context_id"
43
+ A2A_AGENT_TASK_ID_KEY = "task_id"
File without changes
@@ -0,0 +1,107 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Protocol, runtime_checkable
4
+
5
+ if TYPE_CHECKING:
6
+ from rasa.agents.core.types import ProtocolType
7
+ from rasa.agents.schemas.agent_input import AgentInput
8
+ from rasa.agents.schemas.agent_output import AgentOutput
9
+ from rasa.core.available_agents import AgentConfig
10
+
11
+
12
+ @runtime_checkable
13
+ class AgentProtocol(Protocol):
14
+ """
15
+ Python protocol for interfacing with agent clients that implement the
16
+ agent communication protocols like MCP, A2A, ACP, etc.
17
+ """
18
+
19
+ @classmethod
20
+ def from_config(cls, config: AgentConfig) -> AgentProtocol:
21
+ """Initialize the Agent with the given configuration.
22
+
23
+ This class method should be implemented to parse the given
24
+ configuration and create an instance of an agent.
25
+
26
+ Args:
27
+ config: The configuration for the agent as an AgentConfig object.
28
+
29
+ Returns:
30
+ An instance of the agent.
31
+ """
32
+ ...
33
+
34
+ @property
35
+ def protocol_type(self) -> "ProtocolType":
36
+ """
37
+ Returns the protocol type of the agent.
38
+
39
+ This property should be implemented to return the protocol type of the agent.
40
+ This is used to determine the type of agent to create in the AgentFactory.
41
+ """
42
+ ...
43
+
44
+ async def connect(self) -> None:
45
+ """
46
+ Establish connection to agent/server.
47
+
48
+ This method should be implemented to establish a connection to the agent/server
49
+ and load any necessary resources.
50
+ """
51
+ ...
52
+
53
+ async def disconnect(self) -> None:
54
+ """
55
+ Close connection to agent/server.
56
+
57
+ This method should be implemented to close the connection to the agent/server
58
+ and release any necessary resources.
59
+ """
60
+ ...
61
+
62
+ async def process_input(self, input: "AgentInput") -> "AgentInput":
63
+ """
64
+ Pre-process the input before sending it to the agent.
65
+
66
+ This method should be implemented to pre-process the input before sending it
67
+ to the agent. This can be used to add any necessary metadata or context to the
68
+ input, or to filter the input.
69
+
70
+ Args:
71
+ input: The input to the agent as an AgentInput object.
72
+
73
+ Returns:
74
+ The processed input to the agent as an AgentInput object.
75
+ """
76
+ ...
77
+
78
+ async def run(self, input: "AgentInput") -> "AgentOutput":
79
+ """
80
+ Send a message to Agent/server and return response.
81
+
82
+ This method should be implemented to send a message to the agent/server and
83
+ return the response in an AgentOutput object.
84
+
85
+ Args:
86
+ input: The input to the agent as an AgentInput object.
87
+
88
+ Returns:
89
+ The output from the agent as an AgentOutput object.
90
+ """
91
+ ...
92
+
93
+ async def process_output(self, output: "AgentOutput") -> "AgentOutput":
94
+ """
95
+ Post-process the output before returning it to Rasa.
96
+
97
+ This method should be implemented to post-process the output before returning
98
+ it to Rasa. This can be used to add any necessary metadata or context to the
99
+ output, or to filter the output.
100
+
101
+ Args:
102
+ output: The output from the agent as an AgentOutput object.
103
+
104
+ Returns:
105
+ The processed output from the agent as an AgentOutput object.
106
+ """
107
+ ...
@@ -0,0 +1,81 @@
1
+ """Fundamental types for the agent protocol."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class ProtocolType(Enum):
7
+ """An Enum class that represents the supported protocol types."""
8
+
9
+ MCP_OPEN = "mcp_open"
10
+ MCP_TASK = "mcp_task"
11
+ A2A = "a2a"
12
+
13
+
14
+ class AgentIdentifier:
15
+ """Represents a unique agent identifier combining agent_id and protocol_type."""
16
+
17
+ SEPARATOR = "::"
18
+
19
+ def __init__(self, agent_name: str, protocol_type: ProtocolType):
20
+ self.agent_name = agent_name
21
+ self.protocol_type = protocol_type
22
+
23
+ def __str__(self) -> str:
24
+ return f"{self.agent_name}{self.SEPARATOR}{self.protocol_type.value}"
25
+
26
+ def __repr__(self) -> str:
27
+ return (
28
+ f"AgentIdentifier(agent_name='{self.agent_name}', "
29
+ f"protocol_type='{self.protocol_type.value}')"
30
+ )
31
+
32
+ def __eq__(self, other: object) -> bool:
33
+ if isinstance(other, AgentIdentifier):
34
+ return (
35
+ self.agent_name == other.agent_name
36
+ and self.protocol_type == other.protocol_type
37
+ )
38
+ elif isinstance(other, str):
39
+ return str(self) == other
40
+ return False
41
+
42
+ def __hash__(self) -> int:
43
+ return hash((self.agent_name, self.protocol_type))
44
+
45
+ @classmethod
46
+ def from_string(cls, identifier: str) -> "AgentIdentifier":
47
+ """Create an AgentIdentifier from a string representation."""
48
+ if cls.SEPARATOR not in identifier:
49
+ raise ValueError(f"Invalid agent identifier format: {identifier}")
50
+
51
+ parts = identifier.split(cls.SEPARATOR, 1)
52
+ if len(parts) != 2:
53
+ raise ValueError(f"Invalid agent identifier format: {identifier}")
54
+
55
+ agent_name, protocol_str = parts
56
+ try:
57
+ protocol_type = ProtocolType(protocol_str)
58
+ except ValueError:
59
+ raise ValueError(f"Invalid protocol type: {protocol_str}")
60
+
61
+ return cls(agent_name, protocol_type)
62
+
63
+
64
+ class AgentStatus(Enum):
65
+ """A Enum class that represents the status of the agent."""
66
+
67
+ COMPLETED = "completed"
68
+ INPUT_REQUIRED = "input_required"
69
+ FATAL_ERROR = "fatal_error"
70
+ RECOVERABLE_ERROR = "recoverable_error"
71
+
72
+ def __str__(self) -> str:
73
+ return self.value
74
+
75
+ def __repr__(self) -> str:
76
+ return f"AgentStatus.{self.value}"
77
+
78
+ def __eq__(self, other: object) -> bool:
79
+ if isinstance(other, AgentStatus):
80
+ return self.value == other.value
81
+ return False
@@ -0,0 +1,38 @@
1
+ from rasa.exceptions import RasaException, ValidationError
2
+
3
+
4
+ class AgentNotFoundException(RasaException):
5
+ """Raised when an agent is not found."""
6
+
7
+ def __init__(self, agent_name: str):
8
+ super().__init__(f"The agent {agent_name} is not defined.")
9
+
10
+
11
+ class DuplicatedAgentNameException(ValidationError):
12
+ """Raised when agent names are duplicated."""
13
+
14
+ def __init__(self, duplicated_names: list[str]) -> None:
15
+ """Initialize the exception."""
16
+ event_info = f"Agent names are duplicated: {', '.join(duplicated_names)}"
17
+
18
+ super().__init__(
19
+ code="agent.duplicated_name",
20
+ event_info=event_info,
21
+ duplicated_names=duplicated_names,
22
+ )
23
+
24
+
25
+ class AgentNameFlowConflictException(ValidationError):
26
+ """Raised when agent names conflict with flow names."""
27
+
28
+ def __init__(self, conflicting_names: list[str]) -> None:
29
+ """Initialize the exception."""
30
+ event_info = (
31
+ f"Agent names conflict with flow names: {', '.join(conflicting_names)}"
32
+ )
33
+
34
+ super().__init__(
35
+ code="agent.flow_name_conflict",
36
+ event_info=event_info,
37
+ conflicting_names=conflicting_names,
38
+ )
@@ -0,0 +1,5 @@
1
+ from rasa.agents.protocol.a2a.a2a_agent import A2AAgent
2
+ from rasa.agents.protocol.mcp.mcp_open_agent import MCPOpenAgent
3
+ from rasa.agents.protocol.mcp.mcp_task_agent import MCPTaskAgent
4
+
5
+ __all__ = ["A2AAgent", "MCPOpenAgent", "MCPTaskAgent"]
File without changes