open-swarm 0.1.1745275181__py3-none-any.whl → 0.1.1748636295__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.
Files changed (307) hide show
  1. open_swarm-0.1.1748636295.dist-info/METADATA +257 -0
  2. open_swarm-0.1.1748636295.dist-info/RECORD +89 -0
  3. {open_swarm-0.1.1745275181.dist-info → open_swarm-0.1.1748636295.dist-info}/WHEEL +2 -1
  4. open_swarm-0.1.1748636295.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1748636295.dist-info/top_level.txt +1 -0
  6. swarm/__init__.py +2 -0
  7. swarm/agent/agent.py +49 -0
  8. swarm/auth.py +48 -113
  9. swarm/consumers.py +0 -19
  10. swarm/core.py +411 -0
  11. swarm/extensions/blueprint/__init__.py +16 -30
  12. swarm/extensions/blueprint/agent_utils.py +45 -0
  13. swarm/extensions/blueprint/blueprint_base.py +562 -0
  14. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  15. swarm/extensions/blueprint/django_utils.py +79 -181
  16. swarm/extensions/blueprint/interactive_mode.py +72 -67
  17. swarm/extensions/blueprint/output_utils.py +82 -0
  18. swarm/{core → extensions/blueprint}/spinner.py +21 -30
  19. swarm/extensions/cli/cli_args.py +0 -6
  20. swarm/extensions/cli/commands/blueprint_management.py +9 -47
  21. swarm/extensions/cli/commands/config_management.py +6 -5
  22. swarm/extensions/cli/commands/edit_config.py +7 -16
  23. swarm/extensions/cli/commands/list_blueprints.py +1 -1
  24. swarm/extensions/cli/commands/validate_env.py +4 -11
  25. swarm/extensions/cli/commands/validate_envvars.py +6 -6
  26. swarm/extensions/cli/interactive_shell.py +2 -16
  27. swarm/extensions/config/config_loader.py +345 -107
  28. swarm/{core → extensions/config}/config_manager.py +38 -50
  29. swarm/{core → extensions/config}/server_config.py +0 -32
  30. swarm/extensions/launchers/build_launchers.py +14 -0
  31. swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
  32. swarm/extensions/launchers/swarm_api.py +64 -8
  33. swarm/extensions/launchers/swarm_cli.py +300 -8
  34. swarm/extensions/mcp/__init__.py +1 -0
  35. swarm/extensions/mcp/cache_utils.py +32 -0
  36. swarm/extensions/mcp/mcp_client.py +233 -0
  37. swarm/extensions/mcp/mcp_tool_provider.py +135 -0
  38. swarm/extensions/mcp/mcp_utils.py +260 -0
  39. swarm/llm/chat_completion.py +166 -0
  40. swarm/serializers.py +5 -96
  41. swarm/settings.py +133 -85
  42. swarm/types.py +91 -0
  43. swarm/urls.py +74 -57
  44. swarm/utils/context_utils.py +4 -10
  45. swarm/utils/general_utils.py +0 -21
  46. swarm/utils/redact.py +36 -23
  47. swarm/views/api_views.py +39 -48
  48. swarm/views/chat_views.py +76 -236
  49. swarm/views/core_views.py +87 -80
  50. swarm/views/model_views.py +121 -64
  51. swarm/views/utils.py +439 -65
  52. swarm/views/web_views.py +2 -2
  53. open_swarm-0.1.1745275181.dist-info/METADATA +0 -874
  54. open_swarm-0.1.1745275181.dist-info/RECORD +0 -319
  55. open_swarm-0.1.1745275181.dist-info/entry_points.txt +0 -4
  56. swarm/blueprints/README.md +0 -68
  57. swarm/blueprints/blueprint_audit_status.json +0 -27
  58. swarm/blueprints/chatbot/README.md +0 -40
  59. swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
  60. swarm/blueprints/chatbot/metadata.json +0 -23
  61. swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
  62. swarm/blueprints/chucks_angels/README.md +0 -11
  63. swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
  64. swarm/blueprints/chucks_angels/test_basic.py +0 -3
  65. swarm/blueprints/codey/CODEY.md +0 -15
  66. swarm/blueprints/codey/README.md +0 -115
  67. swarm/blueprints/codey/blueprint_codey.py +0 -1072
  68. swarm/blueprints/codey/codey_cli.py +0 -373
  69. swarm/blueprints/codey/instructions.md +0 -17
  70. swarm/blueprints/codey/metadata.json +0 -23
  71. swarm/blueprints/common/operation_box_utils.py +0 -83
  72. swarm/blueprints/digitalbutlers/README.md +0 -11
  73. swarm/blueprints/digitalbutlers/__init__.py +0 -1
  74. swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
  75. swarm/blueprints/digitalbutlers/test_basic.py +0 -3
  76. swarm/blueprints/divine_code/README.md +0 -3
  77. swarm/blueprints/divine_code/__init__.py +0 -10
  78. swarm/blueprints/divine_code/apps.py +0 -11
  79. swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
  80. swarm/blueprints/django_chat/apps.py +0 -6
  81. swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
  82. swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
  83. swarm/blueprints/django_chat/urls.py +0 -8
  84. swarm/blueprints/django_chat/views.py +0 -32
  85. swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
  86. swarm/blueprints/flock/README.md +0 -11
  87. swarm/blueprints/flock/__init__.py +0 -8
  88. swarm/blueprints/flock/blueprint_flock.py +0 -7
  89. swarm/blueprints/flock/test_basic.py +0 -3
  90. swarm/blueprints/geese/README.md +0 -10
  91. swarm/blueprints/geese/__init__.py +0 -8
  92. swarm/blueprints/geese/blueprint_geese.py +0 -384
  93. swarm/blueprints/geese/geese_cli.py +0 -102
  94. swarm/blueprints/jeeves/README.md +0 -41
  95. swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
  96. swarm/blueprints/jeeves/jeeves_cli.py +0 -55
  97. swarm/blueprints/jeeves/metadata.json +0 -24
  98. swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
  99. swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
  100. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
  101. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
  102. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
  103. swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
  104. swarm/blueprints/poets/blueprint_poets.py +0 -546
  105. swarm/blueprints/poets/poets_cli.py +0 -23
  106. swarm/blueprints/rue_code/README.md +0 -8
  107. swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
  108. swarm/blueprints/rue_code/rue_code_cli.py +0 -43
  109. swarm/blueprints/stewie/apps.py +0 -12
  110. swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
  111. swarm/blueprints/stewie/models.py +0 -19
  112. swarm/blueprints/stewie/serializers.py +0 -10
  113. swarm/blueprints/stewie/settings.py +0 -17
  114. swarm/blueprints/stewie/urls.py +0 -11
  115. swarm/blueprints/stewie/views.py +0 -26
  116. swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
  117. swarm/blueprints/whinge_surf/README.md +0 -22
  118. swarm/blueprints/whinge_surf/__init__.py +0 -1
  119. swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
  120. swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
  121. swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  122. swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
  123. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
  124. swarm/blueprints/zeus/__init__.py +0 -2
  125. swarm/blueprints/zeus/apps.py +0 -4
  126. swarm/blueprints/zeus/blueprint_zeus.py +0 -270
  127. swarm/blueprints/zeus/zeus_cli.py +0 -13
  128. swarm/cli/async_input.py +0 -65
  129. swarm/cli/async_input_demo.py +0 -32
  130. swarm/core/agent_utils.py +0 -21
  131. swarm/core/blueprint_base.py +0 -769
  132. swarm/core/blueprint_discovery.py +0 -125
  133. swarm/core/blueprint_runner.py +0 -59
  134. swarm/core/blueprint_ux.py +0 -109
  135. swarm/core/build_launchers.py +0 -15
  136. swarm/core/cli/__init__.py +0 -1
  137. swarm/core/cli/commands/__init__.py +0 -1
  138. swarm/core/cli/commands/blueprint_management.py +0 -7
  139. swarm/core/cli/interactive_shell.py +0 -14
  140. swarm/core/cli/main.py +0 -50
  141. swarm/core/cli/utils/__init__.py +0 -1
  142. swarm/core/cli/utils/discover_commands.py +0 -18
  143. swarm/core/config_loader.py +0 -122
  144. swarm/core/output_utils.py +0 -193
  145. swarm/core/session_logger.py +0 -42
  146. swarm/core/slash_commands.py +0 -89
  147. swarm/core/swarm_api.py +0 -68
  148. swarm/core/swarm_cli.py +0 -216
  149. swarm/core/utils/__init__.py +0 -0
  150. swarm/extensions/blueprint/cli_handler.py +0 -197
  151. swarm/extensions/blueprint/runnable_blueprint.py +0 -42
  152. swarm/extensions/cli/utils/__init__.py +0 -1
  153. swarm/extensions/cli/utils/async_input.py +0 -46
  154. swarm/extensions/cli/utils/prompt_user.py +0 -3
  155. swarm/management/__init__.py +0 -0
  156. swarm/management/commands/__init__.py +0 -0
  157. swarm/management/commands/runserver.py +0 -58
  158. swarm/middleware.py +0 -65
  159. swarm/permissions.py +0 -38
  160. swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
  161. swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
  162. swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
  163. swarm/static/contrib/markedjs/marked.min.js +0 -6
  164. swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
  165. swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
  166. swarm/static/contrib/tabler-icons/archive.svg +0 -21
  167. swarm/static/contrib/tabler-icons/artboard.svg +0 -27
  168. swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
  169. swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
  170. swarm/static/contrib/tabler-icons/carambola.svg +0 -19
  171. swarm/static/contrib/tabler-icons/copy.svg +0 -20
  172. swarm/static/contrib/tabler-icons/download.svg +0 -21
  173. swarm/static/contrib/tabler-icons/edit.svg +0 -21
  174. swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
  175. swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
  176. swarm/static/contrib/tabler-icons/headset.svg +0 -22
  177. swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
  178. swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
  179. swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
  180. swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
  181. swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
  182. swarm/static/contrib/tabler-icons/message-star.svg +0 -22
  183. swarm/static/contrib/tabler-icons/message-x.svg +0 -23
  184. swarm/static/contrib/tabler-icons/message.svg +0 -21
  185. swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
  186. swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
  187. swarm/static/contrib/tabler-icons/robot.svg +0 -26
  188. swarm/static/contrib/tabler-icons/search.svg +0 -19
  189. swarm/static/contrib/tabler-icons/settings.svg +0 -20
  190. swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
  191. swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
  192. swarm/static/css/dropdown.css +0 -22
  193. swarm/static/htmx/htmx.min.js +0 -0
  194. swarm/static/js/dropdown.js +0 -23
  195. swarm/static/rest_mode/css/base.css +0 -470
  196. swarm/static/rest_mode/css/chat-history.css +0 -286
  197. swarm/static/rest_mode/css/chat.css +0 -251
  198. swarm/static/rest_mode/css/chatbot.css +0 -74
  199. swarm/static/rest_mode/css/chatgpt.css +0 -62
  200. swarm/static/rest_mode/css/colors/corporate.css +0 -74
  201. swarm/static/rest_mode/css/colors/pastel.css +0 -81
  202. swarm/static/rest_mode/css/colors/tropical.css +0 -82
  203. swarm/static/rest_mode/css/general.css +0 -142
  204. swarm/static/rest_mode/css/layout.css +0 -167
  205. swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
  206. swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
  207. swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
  208. swarm/static/rest_mode/css/messages.css +0 -84
  209. swarm/static/rest_mode/css/messenger.css +0 -135
  210. swarm/static/rest_mode/css/settings.css +0 -91
  211. swarm/static/rest_mode/css/simple.css +0 -44
  212. swarm/static/rest_mode/css/slack.css +0 -58
  213. swarm/static/rest_mode/css/style.css +0 -156
  214. swarm/static/rest_mode/css/theme.css +0 -30
  215. swarm/static/rest_mode/css/toast.css +0 -40
  216. swarm/static/rest_mode/js/auth.js +0 -9
  217. swarm/static/rest_mode/js/blueprint.js +0 -41
  218. swarm/static/rest_mode/js/blueprintUtils.js +0 -12
  219. swarm/static/rest_mode/js/chatLogic.js +0 -79
  220. swarm/static/rest_mode/js/debug.js +0 -63
  221. swarm/static/rest_mode/js/events.js +0 -98
  222. swarm/static/rest_mode/js/main.js +0 -19
  223. swarm/static/rest_mode/js/messages.js +0 -264
  224. swarm/static/rest_mode/js/messengerLogic.js +0 -355
  225. swarm/static/rest_mode/js/modules/apiService.js +0 -84
  226. swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
  227. swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
  228. swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
  229. swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
  230. swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
  231. swarm/static/rest_mode/js/modules/state.js +0 -7
  232. swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
  233. swarm/static/rest_mode/js/modules/validation.js +0 -23
  234. swarm/static/rest_mode/js/rendering.js +0 -119
  235. swarm/static/rest_mode/js/settings.js +0 -130
  236. swarm/static/rest_mode/js/sidebar.js +0 -94
  237. swarm/static/rest_mode/js/simpleLogic.js +0 -37
  238. swarm/static/rest_mode/js/slackLogic.js +0 -66
  239. swarm/static/rest_mode/js/splash.js +0 -76
  240. swarm/static/rest_mode/js/theme.js +0 -111
  241. swarm/static/rest_mode/js/toast.js +0 -36
  242. swarm/static/rest_mode/js/ui.js +0 -265
  243. swarm/static/rest_mode/js/validation.js +0 -57
  244. swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
  245. swarm/static/rest_mode/svg/arrow_down.svg +0 -5
  246. swarm/static/rest_mode/svg/arrow_left.svg +0 -5
  247. swarm/static/rest_mode/svg/arrow_right.svg +0 -5
  248. swarm/static/rest_mode/svg/arrow_up.svg +0 -5
  249. swarm/static/rest_mode/svg/attach.svg +0 -8
  250. swarm/static/rest_mode/svg/avatar.svg +0 -7
  251. swarm/static/rest_mode/svg/canvas.svg +0 -6
  252. swarm/static/rest_mode/svg/chat_history.svg +0 -4
  253. swarm/static/rest_mode/svg/close.svg +0 -5
  254. swarm/static/rest_mode/svg/copy.svg +0 -4
  255. swarm/static/rest_mode/svg/dark_mode.svg +0 -3
  256. swarm/static/rest_mode/svg/edit.svg +0 -5
  257. swarm/static/rest_mode/svg/layout.svg +0 -9
  258. swarm/static/rest_mode/svg/logo.svg +0 -29
  259. swarm/static/rest_mode/svg/logout.svg +0 -5
  260. swarm/static/rest_mode/svg/mobile.svg +0 -5
  261. swarm/static/rest_mode/svg/new_chat.svg +0 -4
  262. swarm/static/rest_mode/svg/not_visible.svg +0 -5
  263. swarm/static/rest_mode/svg/plus.svg +0 -7
  264. swarm/static/rest_mode/svg/run_code.svg +0 -6
  265. swarm/static/rest_mode/svg/save.svg +0 -4
  266. swarm/static/rest_mode/svg/search.svg +0 -6
  267. swarm/static/rest_mode/svg/settings.svg +0 -4
  268. swarm/static/rest_mode/svg/speaker.svg +0 -5
  269. swarm/static/rest_mode/svg/stop.svg +0 -6
  270. swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
  271. swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
  272. swarm/static/rest_mode/svg/toggle_off.svg +0 -6
  273. swarm/static/rest_mode/svg/toggle_on.svg +0 -6
  274. swarm/static/rest_mode/svg/trash.svg +0 -10
  275. swarm/static/rest_mode/svg/undo.svg +0 -3
  276. swarm/static/rest_mode/svg/visible.svg +0 -8
  277. swarm/static/rest_mode/svg/voice.svg +0 -10
  278. swarm/templates/account/login.html +0 -22
  279. swarm/templates/account/signup.html +0 -32
  280. swarm/templates/base.html +0 -30
  281. swarm/templates/chat.html +0 -43
  282. swarm/templates/index.html +0 -35
  283. swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
  284. swarm/templates/rest_mode/components/header.html +0 -45
  285. swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
  286. swarm/templates/rest_mode/components/settings_dialog.html +0 -97
  287. swarm/templates/rest_mode/components/splash_screen.html +0 -7
  288. swarm/templates/rest_mode/components/top_bar.html +0 -28
  289. swarm/templates/rest_mode/message_ui.html +0 -50
  290. swarm/templates/rest_mode/slackbot.html +0 -30
  291. swarm/templates/simple_blueprint_page.html +0 -24
  292. swarm/templates/websocket_partials/final_system_message.html +0 -3
  293. swarm/templates/websocket_partials/system_message.html +0 -4
  294. swarm/templates/websocket_partials/user_message.html +0 -5
  295. swarm/utils/ansi_box.py +0 -34
  296. swarm/utils/disable_tracing.py +0 -38
  297. swarm/utils/log_utils.py +0 -63
  298. swarm/utils/openai_patch.py +0 -33
  299. swarm/ux/ansi_box.py +0 -43
  300. swarm/ux/spinner.py +0 -53
  301. {open_swarm-0.1.1745275181.dist-info → open_swarm-0.1.1748636295.dist-info}/licenses/LICENSE +0 -0
  302. /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
  303. /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
  304. /swarm/{core → extensions/config}/setup_wizard.py +0 -0
  305. /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
  306. /swarm/{core → extensions/config}/utils/logger.py +0 -0
  307. /swarm/{core → extensions/launchers}/swarm_wrapper.py +0 -0
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: open-swarm
3
+ Version: 0.1.1748636295
4
+ Summary: A tool for orchestrating Swarm using both CLI and API.
5
+ Author-email: Matthew Hand <matthewhandau@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: aiofiles>=24.1.0
10
+ Requires-Dist: aiohttp>=3.11.11
11
+ Requires-Dist: asyncio>=3.4.3
12
+ Requires-Dist: asynctest>=0.13.0
13
+ Requires-Dist: channels>=4.2.0
14
+ Requires-Dist: colorama>=0.4.6
15
+ Requires-Dist: django<5.0,>=4.2
16
+ Requires-Dist: django-allauth>=65.3.1
17
+ Requires-Dist: django-template-debug>=0.3.5
18
+ Requires-Dist: djangorestframework>=3.15.2
19
+ Requires-Dist: flask>=3.1.0
20
+ Requires-Dist: jmespath>=1.0.1
21
+ Requires-Dist: jsonschema-pydantic>=0.6
22
+ Requires-Dist: mcp>=1.2.0
23
+ Requires-Dist: openai>=1.58.1
24
+ Requires-Dist: python-dotenv>=1.0.1
25
+ Requires-Dist: redis>=5.2.1
26
+ Requires-Dist: requests>=2.32.3
27
+ Requires-Dist: whitenoise>=6.8.2
28
+ Requires-Dist: drf-spectacular>=0.23.0
29
+ Requires-Dist: pyinstaller>=6.12.0
30
+ Requires-Dist: tiktoken>=0.9.0
31
+ Requires-Dist: django-cors-headers>=4.7.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=8.3.4; extra == "dev"
34
+ Requires-Dist: pytest-asyncio>=0.25.1; extra == "dev"
35
+ Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
36
+ Requires-Dist: pytest-django>=4.9.0; extra == "dev"
37
+ Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
38
+ Requires-Dist: python-semantic-release>=9.20.0; extra == "dev"
39
+ Provides-Extra: experimental
40
+ Requires-Dist: nemoguardrails>=0.11.0; extra == "experimental"
41
+ Dynamic: license-file
42
+
43
+ # Open Swarm
44
+
45
+ <div align="center">
46
+ <img src="assets/images/openswarm-project-image.jpg" alt="Project Logo" width="70%"/>
47
+ </div>
48
+
49
+ **Open Swarm** is a versatile, modular framework for building intelligent, multi-agent systems. It's a **fork and actively maintained extension** of the [OpenAI Swarm](https://github.com/openai/swarm) framework. It includes modifications to support stateless RESTful operations and a plugin system for custom extensions that enhance agentic workflows.
50
+
51
+ ---
52
+
53
+ https://github.com/user-attachments/assets/1335f7fb-ff61-4e96-881c-7d3154eb9f14
54
+
55
+ (generated by www.gitpodcast.com)
56
+
57
+ ---
58
+
59
+ ## Table of Contents
60
+ - [Key Features](#key-features)
61
+ - [Quickstart](#quickstart)
62
+ - [Blueprints](#blueprints)
63
+ - [Further Documentation](#further-documentation)
64
+ - [License](#license)
65
+ - [Acknowledgements](#acknowledgements)
66
+
67
+ ---
68
+
69
+ ## Key Features
70
+
71
+ 1. **Multi-Agent Orchestration**
72
+ - Define multiple agents, each with unique instructions and roles.
73
+ - Agents coordinate tasks, share context, or hand off queries between one another.
74
+
75
+ 2. **Blueprint-Driven Architecture**
76
+ - Each **Blueprint** encapsulates logic, tool connections, and environment/config settings.
77
+ - Encourages reusable, modular patterns for different use cases.
78
+
79
+ 3. **Optional MCP Integration**
80
+ - Integrate with external tools (e.g., databases, web search, filesystems) through **MCP servers**.
81
+ - Note `npx` MCP servers work great but `uvx` MCP servers currently have issues.
82
+
83
+ 4. **CLI & REST Interface**
84
+ - Run from the command line or expose a Django-powered REST API for broader integration.
85
+ - Interactive web pages per blueprint at `/<blueprint_name>/`.
86
+
87
+ 5. **OpenAI API Compatibility**
88
+ - Exposes an endpoint at `/v1/chat/completions` that is functionally similar to the OpenAI Chat Completions API.
89
+ - Includes a **mandatory** `sender` field in agent responses.
90
+ - This field identifies which Swarm agent provided the response and must be preserved in the conversation history for proper handoffs between agents.
91
+ - While the framework is compatible with OpenAI-like API clients, it assumes the client application maintains the `sender` field and, ideally, displays it in the user interface.
92
+ - **Note:** Most OpenAI API-compatible applications will ignore the `sender` field by default and not display the agent name. Custom UI or logic is required to utilise and present this information.
93
+
94
+ 6. **Configurable LLMs**
95
+ - Supports multiple OpenAI-compatible providers in a single environment (e.g., `openai`, `grok`, `ollama`).
96
+ - Allows specifying different models/providers for different agents—even within the same blueprint.
97
+ - Use environment variable `DEFAULT_LLM` to specify default LLM model used by blueprints, e.g., `DEFAULT_LLM=deepseek-r1-distill-llama-70b`
98
+
99
+ ---
100
+
101
+ ## Quickstart
102
+
103
+ Follow these simple steps to get Open Swarm up and running:
104
+
105
+ 1. **Install the Package**
106
+ Run:
107
+ ```bash
108
+ pip install open-swarm
109
+ ```
110
+
111
+ 2. **Configure an LLM Provider**
112
+ When you run a blueprint for the first time, Open Swarm checks for a configuration file at `~/.swarm/swarm_config.json`. If the file is missing, it will automatically create a default configuration as shown below:
113
+ ```json
114
+ {
115
+ "llm": {
116
+ "default": {
117
+ "provider": "openai",
118
+ "model": "gpt-4o",
119
+ "base_url": "https://api.openai.com/v1",
120
+ "api_key": "${OPENAI_API_KEY}"
121
+ }
122
+ },
123
+ "mcpServers": {}
124
+ }
125
+ ```
126
+ Make sure to set the `OPENAI_API_KEY` environment variable with your valid OpenAI API key.
127
+
128
+ An example of using an alternative provider:
129
+
130
+ `swarm-cli config add --section llm --name deepseek-r1-distill-llama-70b --json '{"provider": "openai", "model": "deepseek-r1-distill-llama-70b", "base_url": "https://api.groq.com/openai/v1", "api_key": "${GROQ_API_KEY}"}' `
131
+
132
+
133
+ 3. **(Optional) Configure a Simple MCP Server**
134
+ To add an MCP server for additional utilities (e.g., file fetching), use the `swarm-cli config add --json '<multiline_json_block>'`. For example:
135
+
136
+ ```json
137
+ "filesystem": {
138
+ "command": "npx",
139
+ "args": [
140
+ "-y",
141
+ "@modelcontextprotocol/server-filesystem ${ALLOWED_PATH}"
142
+ ],
143
+ "env": {
144
+ "ALLOWED_PATH": "${ALLOWED_PATH}"
145
+ }
146
+ }
147
+ ```
148
+
149
+ 4. **Add an Example Blueprint**
150
+ Add an example blueprint by running:
151
+ ```bash
152
+ swarm-cli add /path/to/your/blueprint.py --name example
153
+ ```
154
+ This copies your blueprint into the managed blueprints directory.
155
+
156
+ Example blueprints are provided here: https://github.com/matthewhand/open-swarm/tree/main/blueprints
157
+
158
+ 5. **Run the Blueprint from CLI**
159
+ Execute the blueprint with:
160
+ ```bash
161
+ swarm-cli run example
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Overview
167
+
168
+ Open Swarm provides the following core components:
169
+
170
+ - **Swarm CLI:**
171
+ A command-line tool for managing blueprints and configuration settings. It allows you to add, list, delete, run, and install blueprints, as well as update configuration entries for LLM providers and MCP servers.
172
+
173
+ - **Swarm API:**
174
+ An HTTP REST service that exposes endpoints such as `/v1/models` and `/v1/chat/completion(s)`. These endpoints let external applications interact with Open Swarm in an OpenAI API-compatible manner, publishing blueprints as models and processing chat completions. Additional endpoints can be exposed via blueprints.
175
+
176
+ - **Swarm SDK:**
177
+ Open Swarm can be used as a Python module. It is backwards compatible with the original OpenAI Swarm educational framework. It also adds many extensions including configuration loading, MCP server integration, Python Django DB and REST features, etc etc.
178
+
179
+ For detailed usage instructions, please refer to the [USERGUIDE.md](./USERGUIDE.md). For developer-specific guidance, see [DEVELOPMENT.md](./DEVELOPMENT.md).
180
+
181
+ ---
182
+
183
+
184
+ ## Blueprints
185
+
186
+ A **Blueprint** is a Python module that wraps:
187
+
188
+ - **Agent Logic**: Defines how each agent in the Swarm processes user messages, whether it calls tools, and how it decides to hand off to other agents.
189
+ - **Tools**: Specifies which agents have which tools (e.g., MCP-discovered tools, Python function calls).
190
+ - **Environment & Configuration**: Ensures required environment variables and JSON configs are validated prior to agent execution.
191
+
192
+ Once registered, a blueprint is discoverable at runtime, allowing the system to list and load agents on demand.
193
+
194
+ ### Personal Assistant Example
195
+
196
+ The **Personal Assistant Blueprint** demonstrates a hybrid approach, integrating **local Python function tools** with **MCP-discovered tools**. It consists of:
197
+
198
+ 1. **Personal Assistant Agent**
199
+ - Determines user intent and delegates queries accordingly.
200
+ - Routes weather-related queries to the `WeatherAgent`.
201
+ - Routes knowledge-based queries to the `DocumentationAgent`.
202
+
203
+ 2. **Weather Agent** (Uses Python Function Tools)
204
+ - Fetches current weather and forecasts via OpenWeatherMap.
205
+ - Uses a **locally defined Python function** rather than an MCP server.
206
+ - Requires `WEATHER_API_KEY` as an environment variable.
207
+
208
+ 3. **Documentation Agent** (Uses MCP-Discovered Tools)
209
+ - Retrieves relevant documentation via `rag-docs`.
210
+ - Uses the MCP function `search_documentation` to dynamically retrieve information.
211
+ - Requires the following environment variables:
212
+ - `OPENAI_API_KEY`
213
+ - `QDRANT_URL`
214
+ - `QDRANT_API_KEY`
215
+
216
+ This blueprint highlights **seamless multi-agent coordination** and the **flexibility of combining Python functions with MCP-discovered tools**.
217
+
218
+ ### Other Examples
219
+
220
+ Open Swarm includes a growing library of **Blueprint** examples:
221
+
222
+ | Blueprint Name | Description | Status |
223
+ |------------------------------|-----------------------------------------------------------------------------|-----------------------------------------|
224
+ | **Echo Blueprint** | A straightforward agent that simply echoes user inputs—ideal for testing or as a starter template. | Stable |
225
+ | **Suggestion Blueprint** | Blueprint providing suggestions and recommendations. | Stable |
226
+ | **Database and Web Blueprint** | Demonstrates MCP-based integration with an SQLite database and Brave Search, illustrating how to combine data retrieval with real-time web queries. | Stable |
227
+ | **University Blueprint** | Multi-agent system for university-related tasks. | Stable |
228
+ | **Divine Ops Blueprint** | Multi-agent system for handling system administration tasks using MCP tools (filesystem, SQLite, search, etc.). | Stable |
229
+ | **Nebucha Shellzzar Blueprint**| Example system administration blueprint. | Stable |
230
+ | **Personal Assistant Blueprint** | Combines real-time weather updates (Python function) with documentation search (`rag-docs`, MCP). Demonstrates mixed tooling. | Broken (uvx-based) |
231
+ | **Flowise Blueprint** | Integrates with Flowise for visual flow orchestration. | Broken (uvx-based, requires Flowise setup)|
232
+
233
+ ---
234
+ ---
235
+
236
+ ## Further Documentation
237
+
238
+ For advanced usage, sequence diagrams, or in-depth tooling examples, see [DEVELOPMENT.md](./DEVELOPMENT.md). Additional expansions and best practices for agent orchestration, LLM provider swapping, and more can be found in that document.
239
+
240
+ ---
241
+
242
+ ## License
243
+
244
+ Open Swarm is provided under the MIT License. Refer to the [LICENSE](LICENSE) file for full details.
245
+
246
+ ---
247
+
248
+ ## Acknowledgements
249
+
250
+ This project is based on the [OpenAI Swarm](https://github.com/openai/swarm) framework. We would like to acknowledge the original authors and contributors of this project for their work.
251
+ We also wish to credit [django_chatbot](https://github.com/MattiPaivike/django_chatbot) for the Django chatbot view.
252
+
253
+ ### Third-Party Libraries
254
+ - **[Marked.js](https://github.com/markedjs/marked)** (MIT License)
255
+ A fast, lightweight library for parsing Markdown into HTML.
256
+ - **[Tabler Icons](https://tablericons.com)** (MIT License)
257
+ A set of free, high-quality SVG icons for web projects, designed by Paweł Kuna.
@@ -0,0 +1,89 @@
1
+ open_swarm-0.1.1748636295.dist-info/licenses/LICENSE,sha256=BU9bwRlnOt_JDIb6OT55Q4leLZx9RArDLTFnlDIrBEI,1062
2
+ swarm/__init__.py,sha256=N2hwTgbJPoezNcg9WQCK0rj6Ap7MuyprhkWSDTfb9pI,71
3
+ swarm/apps.py,sha256=up4C3m2JeyXeUcH-wYeReCuiOBVJ6404w9OfaRChLwM,2568
4
+ swarm/auth.py,sha256=WcajB6lrA2cSA-Ho1lnBEs9_MNtDx713sxHRvIXx9fQ,2415
5
+ swarm/consumers.py,sha256=wESLamkhbi4SEZt9k3yx6eU9ufOIZMCAL-OAXjJBGXE,5056
6
+ swarm/core.py,sha256=9SYH9JRs2OrSKdJrWK4OdcjmItpEEfY44ou7DSh_X94,22249
7
+ swarm/messages.py,sha256=CwADrjlj-uVmm-so1xIZvN1UkEWdzSn_hu7slfhuS8w,6549
8
+ swarm/models.py,sha256=Ix0WEYYqza2lbOEBNesikRCs3XGUPWmqQyMWzZYUaxM,1494
9
+ swarm/serializers.py,sha256=EPvQHvUZtnOKX5ltddNFPGnWaJGxFDWFbofTa39oxgE,363
10
+ swarm/settings.py,sha256=CQyql6M0NmARGTzaeQHogRDNCsiQp6orJ_hjSkxn8V0,7956
11
+ swarm/tool_executor.py,sha256=KHM2mTGgbbTgWNN3fbV5c4MDY238OTLwaaqtkczFHFQ,12385
12
+ swarm/types.py,sha256=3Uw7B4O1cvq2j8wuk7_xTrNSgpyOXzRzo8uS72PvXTY,3135
13
+ swarm/urls.py,sha256=i7qIwlSMsMSMrOhkbiUfTEL7tdhRFY4g5prfBimKOX0,4085
14
+ swarm/util.py,sha256=G4x2hXopHhB7IdGCkUXGoykYWyiICnjxg7wcr-WqL8I,4644
15
+ swarm/wsgi.py,sha256=REM_u4HpMCkO0ddrOUXgtY-ITL-VTbRB1-WHvFJAtAU,408
16
+ swarm/agent/__init__.py,sha256=YESGu_UXEBxrlQwghodUMN0vmXZDwWMU7DclCUvoklA,104
17
+ swarm/agent/agent.py,sha256=-lGc05pGmveptO4oZoJq_L6XoTAIpxE8knTc6jxRmEQ,1680
18
+ swarm/extensions/__init__.py,sha256=SadbzfxckByaaqzuKPfXMvqmj45-dcMlavlfQYhGnzE,56
19
+ swarm/extensions/blueprint/__init__.py,sha256=-nAm6l7-42eAJYhWkQlcfq2hQB5ipxg2YIyiQRttX3c,1583
20
+ swarm/extensions/blueprint/agent_utils.py,sha256=GLnjtLhtGW9k1vI9uqMojXcY-OkPXwdmQKLhs60CJ5k,1913
21
+ swarm/extensions/blueprint/blueprint_base.py,sha256=hqvOQ3wS7OJNmqJgpH7IOjLTr3qyHf4XzXxqkkrGYzU,30478
22
+ swarm/extensions/blueprint/blueprint_discovery.py,sha256=ihrIHo4mDaSAUVREXD1y26d5UmPnxVZtBwDGcDJeYrU,5139
23
+ swarm/extensions/blueprint/blueprint_utils.py,sha256=Ef_pu-RYomqzFjMg6LOSPSdbYFCbYXjEoSvK1OT49Eo,702
24
+ swarm/extensions/blueprint/common_utils.py,sha256=jeKcN3lMdrpOYWIpErH3L5am13jHjaImpVvk2b0mps4,462
25
+ swarm/extensions/blueprint/django_utils.py,sha256=y3cGNXgCv4pqWFbVfLr3SmkKLAtwcJvf5JvoQphqAB0,10445
26
+ swarm/extensions/blueprint/interactive_mode.py,sha256=EZaPKnbaw7aeexznI9mk2hEfgJROAljqo2o-ASFN0O4,4594
27
+ swarm/extensions/blueprint/output_utils.py,sha256=ITsK3SgpPR3FVepOaq-P2MmSDIMtOTafepDRZHRt8cM,2883
28
+ swarm/extensions/blueprint/spinner.py,sha256=3J0ZrNzoI5O5qR7hnCeRM3dZx2fLb_H3zkoj_AYt5LQ,3394
29
+ swarm/extensions/blueprint/modes/rest_mode.py,sha256=KZuB_j2NfomER7CmlsLBqRipU3DymKY-9RpoGilMH0I,1357
30
+ swarm/extensions/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ swarm/extensions/cli/blueprint_runner.py,sha256=CG6XfOiDWuc84I_qefBpkwxEs7JcIbvNJqce9jBYUxo,9158
32
+ swarm/extensions/cli/cli_args.py,sha256=Lws6Q3I-DNpzq9qSRN8ylUXg-lWly1SuqDSQF9n50bw,2980
33
+ swarm/extensions/cli/interactive_shell.py,sha256=ocHBP975uqJU5LQyM2IiMVW5lQ387lgYHe3sme9ucX4,1322
34
+ swarm/extensions/cli/main.py,sha256=NnmovA7h1Rj1eDQVYe9AN6-eraIbIclHesNVmQPjdk4,1002
35
+ swarm/extensions/cli/selection.py,sha256=etdG6hJFgnLuvD_sVJvXg8qFcgjzCjyL-vYyxWcU0TI,2002
36
+ swarm/extensions/cli/utils.py,sha256=amDW-jbiM12N-t72j2S0cHP3Mxgoo3nrcwq6CwN9HFY,3290
37
+ swarm/extensions/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ swarm/extensions/cli/commands/blueprint_management.py,sha256=dLNLLoTjInXQ1m9zRyNxu8NacDgwqYY50GvnhSiMQ_I,1116
39
+ swarm/extensions/cli/commands/config_management.py,sha256=RFu9AP437aqUnyy8RDoyoZgW0WfT7h88_CQJaUnCR9E,480
40
+ swarm/extensions/cli/commands/edit_config.py,sha256=O2Y-BKOSx7shSc-kspyseEQvtIeyQBUCD7Aj3r9dirw,2325
41
+ swarm/extensions/cli/commands/list_blueprints.py,sha256=TyZv_dqM_UTK84-s-Dp7UWUcvWHXsNuxnCRNNNymWio,768
42
+ swarm/extensions/cli/commands/validate_env.py,sha256=VXBjx9etvj4Re8qLwIPoHr4g5VwbwBCBdsr8gGLLYHI,1958
43
+ swarm/extensions/cli/commands/validate_envvars.py,sha256=7-BDPYzV7wsga7kOggHNuCscI-7z-oPjMEBhq-ndDXA,1588
44
+ swarm/extensions/cli/utils/discover_commands.py,sha256=aJdU3kSmLlpBxzGdfOA88AaCwpknHSD2cE0piCHZRUY,1053
45
+ swarm/extensions/cli/utils/env_setup.py,sha256=k7QxRjzIGx5HC6RVZP9QSaaXEKMkcKCewD66u0e7qfE,496
46
+ swarm/extensions/config/__init__.py,sha256=WjmGxMU5k3S40TNQxTfByYcT2YAchq_5gzXFWDLrLzU,141
47
+ swarm/extensions/config/config_loader.py,sha256=aOAx6Y3G49vGkRVS2CMX9tDyd-4drPa5cGzzIU8poUQ,21698
48
+ swarm/extensions/config/config_manager.py,sha256=bBT-NGbRdsXoJ-lxZM5kjAf5FvVVGRVdbbCQJiCX1_0,9951
49
+ swarm/extensions/config/server_config.py,sha256=iBlQOaFQmkEPNLmVpAQvXlSWhTsu-YMIjEf-H-7QfUU,1882
50
+ swarm/extensions/config/setup_wizard.py,sha256=yAZ7MOgc8ZGti2kjZ72G6QLFBI0lbhXAa7Wi7SeXDYo,4567
51
+ swarm/extensions/config/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ swarm/extensions/config/utils/logger.py,sha256=sUkKdZsjRiCGGCEPfZ4YqeZDbiaUeGFOa3mdbVOTmvU,1242
53
+ swarm/extensions/launchers/__init__.py,sha256=RR4up00HKqXOOToxb63mKZ2o9fq-o75bUw7dZuxkAVk,56
54
+ swarm/extensions/launchers/build_launchers.py,sha256=Eh3ODR9L4KinG1GDK4-lF3NE0EZ-ArCrP3fxtGYhXgs,433
55
+ swarm/extensions/launchers/build_swarm_wrapper.py,sha256=c_9oR3To4M2cZyc1uYSiysHLhUGX5FkCAQk9AG7Va2Q,231
56
+ swarm/extensions/launchers/swarm_api.py,sha256=f8olTI5JVdayp923etVQWsP8WRquPG5Mw3Q40ItN6kY,2877
57
+ swarm/extensions/launchers/swarm_cli.py,sha256=ar0LxctmxUwhkVbKWLfGEcZB9c77qdPsf1Y33-UNgpY,14184
58
+ swarm/extensions/launchers/swarm_wrapper.py,sha256=3K58yqPN4Ct0c7zfSDKRIGdL1Q7WOBXmAVHXT-aaPj4,1004
59
+ swarm/extensions/mcp/__init__.py,sha256=Rn_lJsxmZZUJrzwig2M63lQxd7P_DX3fZyN1pJt2ps0,49
60
+ swarm/extensions/mcp/cache_utils.py,sha256=i1-EUqJEwLyTZq-_EfIKLafD63_zpmn7gx5TNrFJEfM,952
61
+ swarm/extensions/mcp/mcp_client.py,sha256=M6hOm1D9X8ROncgZe51KW9Bc9a1TfIWAaiJ5uNq8K6o,10972
62
+ swarm/extensions/mcp/mcp_tool_provider.py,sha256=pE2LUJ-j_zC9dIpM3acQB9CxXDrbO74YMFlf_oD-3AI,5700
63
+ swarm/extensions/mcp/mcp_utils.py,sha256=pmVTB7vttexMmMr4FpQbjpVG69Z7iCp7YYXOTaqUhJQ,14560
64
+ swarm/llm/chat_completion.py,sha256=FREzS81pfn3EVg6kraWm8aGFltwLleYaC2MOzCOKBhE,7425
65
+ swarm/migrations/0010_initial_chat_models.py,sha256=qJbvLReRBEOE08FkxjOWMcwu7Ny4epNI_eG1PF8wcWM,1900
66
+ swarm/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ swarm/repl/__init__.py,sha256=hNU3HxjJJi6w5xgx34n3253QJPspFltrK7AM0G_1TlE,32
68
+ swarm/repl/repl.py,sha256=sfVdSiDrStpZyxZehPn0nAxqaja2eySL9v9CfWhZEVc,2609
69
+ swarm/utils/color_utils.py,sha256=utIfZ6ptGEdpHxIZiZ4gtfo5lLqZKQL5g0F8mEwMhTo,1184
70
+ swarm/utils/context_utils.py,sha256=2Eu372CsuDTt6ikZ0w3OkLrFp4t9hKdgU5Kkc8faDDM,19315
71
+ swarm/utils/general_utils.py,sha256=K3_Uy-189XSpLOxKGxl14fa2n7B0ZH28HgysL6vWG-M,7919
72
+ swarm/utils/logger.py,sha256=g-ynqO3jqKx2rT2keiECsZ13aywFPsFlJAvo-SOeGlw,1679
73
+ swarm/utils/logger_setup.py,sha256=2A9bXicV03yAPpgMFJGQt5ePB1tLwdkk7sCo-0OiglU,714
74
+ swarm/utils/message_sequence.py,sha256=7Xa7YwGPgojfkrGcl-SbeR_BWwzXGDYNqAxq8F6XhDc,8616
75
+ swarm/utils/message_utils.py,sha256=oNTD7pfmnnu_Br24pR2VEX9afIZwFLwg2HJBLXs1blY,4074
76
+ swarm/utils/redact.py,sha256=L2lo927S575Ay7Jz6pUlK47Sxxzpd9IMybnDm6-WlC8,2955
77
+ swarm/views/__init__.py,sha256=AcLk0R7Y69FhIVgJK2hZs8M_gCR-h_5iqUywz89yuHM,1223
78
+ swarm/views/api_views.py,sha256=MXt_sWQYUIYgy6gTHSVIeSrszvhtkD-sxQiGBmdbQAg,1815
79
+ swarm/views/chat_views.py,sha256=ch7q7yr-TcP0eoNcO4IhtsVGlhMGLUixBKtsb-Nr_6Q,4299
80
+ swarm/views/core_views.py,sha256=VCv5BEBqUMz6OmQC4RkkIk1qq46f5f7Jyx4MqCaoENo,5229
81
+ swarm/views/message_views.py,sha256=sDUnXyqKXC8WwIIMAlWf00s2_a2T9c75Na5FvYMJwBM,1596
82
+ swarm/views/model_views.py,sha256=2bfqF8LOhgWDRFvm5FeovQDdLcZOS9OfkJLvSC0FDvs,6206
83
+ swarm/views/utils.py,sha256=3EFpCe3sWeQDNnbReFJ-Xdv6KTX6kIMXg23wXQxary4,23678
84
+ swarm/views/web_views.py,sha256=ExQQeJpZ8CkLZQC_pXKOOmdnEy2qR3wEBP4LLp27DPU,7404
85
+ open_swarm-0.1.1748636295.dist-info/METADATA,sha256=_kFKA7JpUHOqO99Re3T7H8qdg4kt8eyq5HCDD6omJJs,11932
86
+ open_swarm-0.1.1748636295.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
87
+ open_swarm-0.1.1748636295.dist-info/entry_points.txt,sha256=tHIcZBvy_sbp_nqZcLG3NSgElG6vEZcUvR5U5325qak,126
88
+ open_swarm-0.1.1748636295.dist-info/top_level.txt,sha256=ETN-2phSZezexCGmKSre_aUhRK0XI9Rzz7Fw5TCsLsQ,6
89
+ open_swarm-0.1.1748636295.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ swarm-api = swarm.extensions.launchers.swarm_api:main
3
+ swarm-cli = swarm.extensions.launchers.swarm_cli:main
@@ -0,0 +1 @@
1
+ swarm
swarm/__init__.py CHANGED
@@ -1 +1,3 @@
1
1
  default_app_config = 'swarm.apps.SwarmConfig'
2
+
3
+ from .core import Swarm
swarm/agent/agent.py ADDED
@@ -0,0 +1,49 @@
1
+ # src/swarm/agent/agent.py
2
+
3
+ from typing import Callable, Dict, Any, List
4
+ import json
5
+
6
+ class Agent:
7
+ def __init__(self, name: str, instructions: str):
8
+ self.name = name
9
+ self.instructions = instructions
10
+ self.tools: Dict[str, Dict[str, Any]] = {}
11
+
12
+ def register_tool(self, name: str, func: Callable[..., Any], description: str = ""):
13
+ """
14
+ Registers a tool with the agent.
15
+
16
+ Args:
17
+ name (str): Name of the tool.
18
+ func (Callable[..., Any]): The function implementing the tool.
19
+ description (str): Description of the tool.
20
+ """
21
+ self.tools[name] = {
22
+ "func": func,
23
+ "description": description
24
+ }
25
+
26
+ async def process(self, query: str) -> str:
27
+ """
28
+ Processes a user query by determining which tool to invoke.
29
+
30
+ Args:
31
+ query (str): The user's query in JSON format specifying the tool and arguments.
32
+
33
+ Returns:
34
+ str: The response from the tool execution.
35
+ """
36
+ try:
37
+ request = json.loads(query)
38
+ tool_name = request.get("tool")
39
+ arguments = request.get("arguments", {})
40
+ if tool_name in self.tools:
41
+ tool_func = self.tools[tool_name]["func"]
42
+ result = await tool_func(**arguments)
43
+ return result
44
+ else:
45
+ return f"Tool '{tool_name}' not found."
46
+ except json.JSONDecodeError:
47
+ return "Invalid query format. Expected JSON with 'tool' and 'arguments'."
48
+ except Exception as e:
49
+ return f"Error processing query: {e}"
swarm/auth.py CHANGED
@@ -1,121 +1,56 @@
1
- import logging
2
1
  import os
3
- from rest_framework.authentication import BaseAuthentication, SessionAuthentication
4
- # Import BasePermission for creating custom permissions
5
- from rest_framework.permissions import BasePermission
6
- from rest_framework import exceptions
7
- from django.conf import settings
8
- from django.utils.translation import gettext_lazy as _
9
- # Import AnonymousUser
2
+ import logging
10
3
  from django.contrib.auth.models import AnonymousUser
11
- # Keep get_user_model if CustomSessionAuthentication needs it or for future user mapping
12
- from django.contrib.auth import get_user_model
4
+ from rest_framework.authentication import TokenAuthentication # type: ignore
5
+ from rest_framework.exceptions import AuthenticationFailed # type: ignore
13
6
 
14
- logger = logging.getLogger('swarm.auth')
15
- User = get_user_model()
7
+ logger = logging.getLogger(__name__)
16
8
 
17
- # ==============================================================================
18
- # Authentication Classes (Determine *who* the user is)
19
- # ==============================================================================
9
+ class EnvAuthenticatedUser(AnonymousUser):
10
+ """ Custom user class that is always authenticated. """
11
+ @property
12
+ def is_authenticated(self) -> bool: # type: ignore[override]
13
+ return True # Ensure Django recognizes this user as authenticated
20
14
 
21
- # --- Static Token Authentication ---
22
- class StaticTokenAuthentication(BaseAuthentication):
15
+ class EnvOrTokenAuthentication(TokenAuthentication):
23
16
  """
24
- Authenticates requests based on a static API token passed in a header
25
- (Authorization: Bearer <token> or X-API-Key: <token>).
26
-
27
- Returns (AnonymousUser, token) on success. This allows permission classes
28
- to check request.auth to see if token authentication succeeded, even though
29
- no specific user model is associated with the token.
17
+ Custom authentication that allows:
18
+ 1. If API_AUTH_TOKEN is set, it enforces token authentication.
19
+ 2. Else if ENABLE_API_AUTH is False/Unset, authentication is bypassed.
20
+ 3. Otherwise, falls back to Django's TokenAuthentication.
30
21
  """
31
- keyword = 'Bearer'
32
-
33
22
  def authenticate(self, request):
34
- """
35
- Attempts to authenticate using a static token.
36
- """
37
- logger.debug("[Auth][StaticToken] Attempting static token authentication.")
38
- # Retrieve the expected token from settings.
39
- expected_token = getattr(settings, 'SWARM_API_KEY', None)
40
-
41
- # If no token is configured in settings, this method cannot authenticate.
42
- if not expected_token:
43
- logger.error("[Auth][StaticToken] SWARM_API_KEY is not set in Django settings. Cannot use static token auth.")
44
- return None # Indicate authentication method did not run or failed pre-check
45
-
46
- # Extract the provided token from standard Authorization header or custom X-API-Key header.
47
- provided_token = None
48
- auth_header = request.META.get('HTTP_AUTHORIZATION', '').split()
49
- if len(auth_header) == 2 and auth_header[0].lower() == self.keyword.lower():
50
- provided_token = auth_header[1]
51
- logger.debug("[Auth][StaticToken] Found token in Authorization header.")
52
- else:
53
- provided_token = request.META.get('HTTP_X_API_KEY')
54
- if provided_token:
55
- logger.debug("[Auth][StaticToken] Found token in X-API-Key header.")
56
-
57
- # If no token was found in either header, authentication fails for this method.
58
- if not provided_token:
59
- logger.debug("[Auth][StaticToken] No token found in relevant headers.")
60
- return None # Indicate authentication method did not find credentials
61
-
62
- # Compare the provided token with the expected token.
63
- # NOTE: For production, consider using a constant-time comparison function
64
- # to mitigate timing attacks if the token is highly sensitive.
65
- if provided_token == expected_token:
66
- logger.info("[Auth][StaticToken] Static token authentication successful.")
67
- # Return AnonymousUser and the token itself as request.auth.
68
- # This signals successful authentication via token without linking to a specific User model.
69
- return (AnonymousUser(), provided_token)
70
- else:
71
- # Token was provided but did not match. Raise AuthenticationFailed.
72
- logger.warning(f"[Auth][StaticToken] Invalid static token provided.")
73
- raise exceptions.AuthenticationFailed(_("Invalid API Key."))
74
-
75
- # --- Custom *Synchronous* Session Authentication ---
76
- class CustomSessionAuthentication(SessionAuthentication):
77
- """
78
- Standard Django Session Authentication provided by DRF.
79
- Relies on Django's session middleware to populate request.user.
80
- This class itself is synchronous, but the underlying session loading
81
- needs to be handled correctly in async views (e.g., via middleware or wrappers).
82
- """
83
- # No override needed unless customizing session behavior.
84
- pass
85
-
86
-
87
- # ==============================================================================
88
- # Permission Classes (Determine *if* access is allowed)
89
- # ==============================================================================
90
-
91
- class HasValidTokenOrSession(BasePermission):
92
- """
93
- Allows access if EITHER:
94
- 1. Static token authentication succeeded (request.auth is not None).
95
- 2. Session authentication succeeded (request.user is authenticated).
96
- """
97
- message = 'Authentication credentials were not provided or are invalid (Requires valid API Key or active session).'
98
-
99
- def has_permission(self, request, view):
100
- """
101
- Checks if the request has valid authentication via token or session.
102
- """
103
- # Check if static token authentication was successful.
104
- # StaticTokenAuthentication returns (AnonymousUser, token), so request.auth will be the token.
105
- has_valid_token = getattr(request, 'auth', None) is not None
106
- if has_valid_token:
107
- logger.debug("[Perm][TokenOrSession] Access granted via static token (request.auth is set).")
108
- return True
109
-
110
- # Check if session authentication was successful.
111
- # request.user should be populated by SessionAuthentication/AuthMiddleware.
112
- user = getattr(request, 'user', None)
113
- has_valid_session = user is not None and user.is_authenticated
114
- if has_valid_session:
115
- logger.debug(f"[Perm][TokenOrSession] Access granted via authenticated session user: {user}")
116
- return True
117
-
118
- # If neither condition is met, deny permission.
119
- logger.debug("[Perm][TokenOrSession] Access denied: No valid token (request.auth=None) and no authenticated session user.")
120
- return False
121
-
23
+ auth_header = request.headers.get("Authorization", "")
24
+ env_token = os.getenv("API_AUTH_TOKEN", None)
25
+ enable_auth = os.getenv("ENABLE_API_AUTH", "false").lower() in ("true", "1", "t")
26
+
27
+ # If API authentication is disabled, allow unrestricted access
28
+ if not enable_auth:
29
+ logger.info("Authentication is disabled (ENABLE_API_AUTH not set or False). Allowing all users.")
30
+ return (EnvAuthenticatedUser(), None)
31
+
32
+ # If API_AUTH_TOKEN is set, enforce token validation
33
+ if env_token:
34
+ if not auth_header:
35
+ raise AuthenticationFailed("Authentication credentials were not provided.")
36
+ if not auth_header.startswith("Bearer "):
37
+ raise AuthenticationFailed("Invalid token format.")
38
+
39
+ token = auth_header.split("Bearer ")[-1].strip()
40
+
41
+ if token == env_token:
42
+ logger.info("Authenticated using API_AUTH_TOKEN.")
43
+ return (EnvAuthenticatedUser(), None) # Allow access
44
+ else:
45
+ raise AuthenticationFailed("Invalid token.")
46
+
47
+ # If API authentication is disabled, allow unrestricted access
48
+ if not enable_auth:
49
+ logger.info("Authentication is disabled (ENABLE_API_AUTH not set or False). Allowing all users.")
50
+ return (EnvAuthenticatedUser(), None)
51
+
52
+ # Fallback to Django's TokenAuthentication
53
+ return super().authenticate(request)
54
+
55
+ def authenticate_header(self, request):
56
+ return "Bearer"
swarm/consumers.py CHANGED
@@ -62,25 +62,6 @@ class DjangoChatConsumer(AsyncWebsocketConsumer):
62
62
  await self.send(text_data=system_message_html)
63
63
 
64
64
  client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
65
-
66
- # --- PATCH: Enforce LiteLLM-only endpoint and suppress OpenAI tracing/telemetry ---
67
- import os, logging
68
- if os.environ.get("LITELLM_BASE_URL") or os.environ.get("OPENAI_BASE_URL"):
69
- logging.getLogger("openai.agents").setLevel(logging.CRITICAL)
70
- try:
71
- import openai.agents.tracing
72
- openai.agents.tracing.TracingClient = lambda *a, **kw: None
73
- except Exception:
74
- pass
75
- def _enforce_litellm_only(client):
76
- base_url = getattr(client, 'base_url', None)
77
- if base_url and 'openai.com' in base_url:
78
- return
79
- if base_url and 'openai.com' not in base_url:
80
- import traceback
81
- raise RuntimeError(f"Attempted fallback to OpenAI API when custom base_url is set! base_url={base_url}\n{traceback.format_stack()}")
82
- _enforce_litellm_only(client)
83
-
84
65
  stream = await client.chat.completions.create(
85
66
  model=os.getenv("OPENAI_MODEL"),
86
67
  messages=self.messages,