agentpool 2.1.9__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 agentpool might be problematic. Click here for more details.

Files changed (474) hide show
  1. acp/README.md +64 -0
  2. acp/__init__.py +172 -0
  3. acp/__main__.py +10 -0
  4. acp/acp_requests.py +285 -0
  5. acp/agent/__init__.py +6 -0
  6. acp/agent/connection.py +256 -0
  7. acp/agent/implementations/__init__.py +6 -0
  8. acp/agent/implementations/debug_server/__init__.py +1 -0
  9. acp/agent/implementations/debug_server/cli.py +79 -0
  10. acp/agent/implementations/debug_server/debug.html +234 -0
  11. acp/agent/implementations/debug_server/debug_server.py +496 -0
  12. acp/agent/implementations/testing.py +91 -0
  13. acp/agent/protocol.py +65 -0
  14. acp/bridge/README.md +162 -0
  15. acp/bridge/__init__.py +6 -0
  16. acp/bridge/__main__.py +91 -0
  17. acp/bridge/bridge.py +246 -0
  18. acp/bridge/py.typed +0 -0
  19. acp/bridge/settings.py +15 -0
  20. acp/client/__init__.py +7 -0
  21. acp/client/connection.py +251 -0
  22. acp/client/implementations/__init__.py +7 -0
  23. acp/client/implementations/default_client.py +185 -0
  24. acp/client/implementations/headless_client.py +266 -0
  25. acp/client/implementations/noop_client.py +110 -0
  26. acp/client/protocol.py +61 -0
  27. acp/connection.py +280 -0
  28. acp/exceptions.py +46 -0
  29. acp/filesystem.py +524 -0
  30. acp/notifications.py +832 -0
  31. acp/py.typed +0 -0
  32. acp/schema/__init__.py +265 -0
  33. acp/schema/agent_plan.py +30 -0
  34. acp/schema/agent_requests.py +126 -0
  35. acp/schema/agent_responses.py +256 -0
  36. acp/schema/base.py +39 -0
  37. acp/schema/capabilities.py +230 -0
  38. acp/schema/client_requests.py +247 -0
  39. acp/schema/client_responses.py +96 -0
  40. acp/schema/common.py +81 -0
  41. acp/schema/content_blocks.py +188 -0
  42. acp/schema/mcp.py +82 -0
  43. acp/schema/messages.py +171 -0
  44. acp/schema/notifications.py +82 -0
  45. acp/schema/protocol_stuff.md +3 -0
  46. acp/schema/session_state.py +160 -0
  47. acp/schema/session_updates.py +419 -0
  48. acp/schema/slash_commands.py +51 -0
  49. acp/schema/terminal.py +15 -0
  50. acp/schema/tool_call.py +347 -0
  51. acp/stdio.py +250 -0
  52. acp/task/__init__.py +53 -0
  53. acp/task/debug.py +197 -0
  54. acp/task/dispatcher.py +93 -0
  55. acp/task/queue.py +69 -0
  56. acp/task/sender.py +82 -0
  57. acp/task/state.py +87 -0
  58. acp/task/supervisor.py +93 -0
  59. acp/terminal_handle.py +30 -0
  60. acp/tool_call_reporter.py +199 -0
  61. acp/tool_call_state.py +178 -0
  62. acp/transports.py +104 -0
  63. acp/utils.py +240 -0
  64. agentpool/__init__.py +63 -0
  65. agentpool/__main__.py +7 -0
  66. agentpool/agents/__init__.py +30 -0
  67. agentpool/agents/acp_agent/__init__.py +5 -0
  68. agentpool/agents/acp_agent/acp_agent.py +837 -0
  69. agentpool/agents/acp_agent/acp_converters.py +294 -0
  70. agentpool/agents/acp_agent/client_handler.py +317 -0
  71. agentpool/agents/acp_agent/session_state.py +44 -0
  72. agentpool/agents/agent.py +1264 -0
  73. agentpool/agents/agui_agent/__init__.py +19 -0
  74. agentpool/agents/agui_agent/agui_agent.py +677 -0
  75. agentpool/agents/agui_agent/agui_converters.py +423 -0
  76. agentpool/agents/agui_agent/chunk_transformer.py +204 -0
  77. agentpool/agents/agui_agent/event_types.py +83 -0
  78. agentpool/agents/agui_agent/helpers.py +192 -0
  79. agentpool/agents/architect.py +71 -0
  80. agentpool/agents/base_agent.py +177 -0
  81. agentpool/agents/claude_code_agent/__init__.py +11 -0
  82. agentpool/agents/claude_code_agent/claude_code_agent.py +1021 -0
  83. agentpool/agents/claude_code_agent/converters.py +243 -0
  84. agentpool/agents/context.py +105 -0
  85. agentpool/agents/events/__init__.py +61 -0
  86. agentpool/agents/events/builtin_handlers.py +129 -0
  87. agentpool/agents/events/event_emitter.py +320 -0
  88. agentpool/agents/events/events.py +561 -0
  89. agentpool/agents/events/tts_handlers.py +186 -0
  90. agentpool/agents/interactions.py +419 -0
  91. agentpool/agents/slashed_agent.py +244 -0
  92. agentpool/agents/sys_prompts.py +178 -0
  93. agentpool/agents/tool_wrapping.py +184 -0
  94. agentpool/base_provider.py +28 -0
  95. agentpool/common_types.py +226 -0
  96. agentpool/config_resources/__init__.py +16 -0
  97. agentpool/config_resources/acp_assistant.yml +24 -0
  98. agentpool/config_resources/agents.yml +109 -0
  99. agentpool/config_resources/agents_template.yml +18 -0
  100. agentpool/config_resources/agui_test.yml +18 -0
  101. agentpool/config_resources/claude_code_agent.yml +16 -0
  102. agentpool/config_resources/claude_style_subagent.md +30 -0
  103. agentpool/config_resources/external_acp_agents.yml +77 -0
  104. agentpool/config_resources/opencode_style_subagent.md +19 -0
  105. agentpool/config_resources/tts_test_agents.yml +78 -0
  106. agentpool/delegation/__init__.py +8 -0
  107. agentpool/delegation/base_team.py +504 -0
  108. agentpool/delegation/message_flow_tracker.py +39 -0
  109. agentpool/delegation/pool.py +1129 -0
  110. agentpool/delegation/team.py +325 -0
  111. agentpool/delegation/teamrun.py +343 -0
  112. agentpool/docs/__init__.py +5 -0
  113. agentpool/docs/gen_examples.py +42 -0
  114. agentpool/docs/utils.py +370 -0
  115. agentpool/functional/__init__.py +20 -0
  116. agentpool/functional/py.typed +0 -0
  117. agentpool/functional/run.py +80 -0
  118. agentpool/functional/structure.py +136 -0
  119. agentpool/hooks/__init__.py +20 -0
  120. agentpool/hooks/agent_hooks.py +247 -0
  121. agentpool/hooks/base.py +119 -0
  122. agentpool/hooks/callable.py +140 -0
  123. agentpool/hooks/command.py +180 -0
  124. agentpool/hooks/prompt.py +122 -0
  125. agentpool/jinja_filters.py +132 -0
  126. agentpool/log.py +224 -0
  127. agentpool/mcp_server/__init__.py +17 -0
  128. agentpool/mcp_server/client.py +429 -0
  129. agentpool/mcp_server/constants.py +32 -0
  130. agentpool/mcp_server/conversions.py +172 -0
  131. agentpool/mcp_server/helpers.py +47 -0
  132. agentpool/mcp_server/manager.py +232 -0
  133. agentpool/mcp_server/message_handler.py +164 -0
  134. agentpool/mcp_server/registries/__init__.py +1 -0
  135. agentpool/mcp_server/registries/official_registry_client.py +345 -0
  136. agentpool/mcp_server/registries/pulsemcp_client.py +88 -0
  137. agentpool/mcp_server/tool_bridge.py +548 -0
  138. agentpool/messaging/__init__.py +58 -0
  139. agentpool/messaging/compaction.py +928 -0
  140. agentpool/messaging/connection_manager.py +319 -0
  141. agentpool/messaging/context.py +66 -0
  142. agentpool/messaging/event_manager.py +426 -0
  143. agentpool/messaging/events.py +39 -0
  144. agentpool/messaging/message_container.py +209 -0
  145. agentpool/messaging/message_history.py +491 -0
  146. agentpool/messaging/messagenode.py +377 -0
  147. agentpool/messaging/messages.py +655 -0
  148. agentpool/messaging/processing.py +76 -0
  149. agentpool/mime_utils.py +95 -0
  150. agentpool/models/__init__.py +21 -0
  151. agentpool/models/acp_agents/__init__.py +22 -0
  152. agentpool/models/acp_agents/base.py +308 -0
  153. agentpool/models/acp_agents/mcp_capable.py +790 -0
  154. agentpool/models/acp_agents/non_mcp.py +842 -0
  155. agentpool/models/agents.py +450 -0
  156. agentpool/models/agui_agents.py +89 -0
  157. agentpool/models/claude_code_agents.py +238 -0
  158. agentpool/models/file_agents.py +116 -0
  159. agentpool/models/file_parsing.py +367 -0
  160. agentpool/models/manifest.py +658 -0
  161. agentpool/observability/__init__.py +9 -0
  162. agentpool/observability/observability_registry.py +97 -0
  163. agentpool/prompts/__init__.py +1 -0
  164. agentpool/prompts/base.py +27 -0
  165. agentpool/prompts/builtin_provider.py +75 -0
  166. agentpool/prompts/conversion_manager.py +95 -0
  167. agentpool/prompts/convert.py +96 -0
  168. agentpool/prompts/manager.py +204 -0
  169. agentpool/prompts/parts/zed.md +33 -0
  170. agentpool/prompts/prompts.py +581 -0
  171. agentpool/py.typed +0 -0
  172. agentpool/queries/tree-sitter-language-pack/README.md +7 -0
  173. agentpool/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  174. agentpool/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  175. agentpool/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  176. agentpool/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
  177. agentpool/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  178. agentpool/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  179. agentpool/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  180. agentpool/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  181. agentpool/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  182. agentpool/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  183. agentpool/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  184. agentpool/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  185. agentpool/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  186. agentpool/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  187. agentpool/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  188. agentpool/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  189. agentpool/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  190. agentpool/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
  191. agentpool/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  192. agentpool/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  193. agentpool/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  194. agentpool/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  195. agentpool/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  196. agentpool/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  197. agentpool/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  198. agentpool/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  199. agentpool/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  200. agentpool/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  201. agentpool/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  202. agentpool/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  203. agentpool/queries/tree-sitter-languages/README.md +24 -0
  204. agentpool/queries/tree-sitter-languages/c-tags.scm +9 -0
  205. agentpool/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  206. agentpool/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  207. agentpool/queries/tree-sitter-languages/dart-tags.scm +91 -0
  208. agentpool/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  209. agentpool/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  210. agentpool/queries/tree-sitter-languages/elm-tags.scm +19 -0
  211. agentpool/queries/tree-sitter-languages/fortran-tags.scm +15 -0
  212. agentpool/queries/tree-sitter-languages/go-tags.scm +30 -0
  213. agentpool/queries/tree-sitter-languages/haskell-tags.scm +3 -0
  214. agentpool/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  215. agentpool/queries/tree-sitter-languages/java-tags.scm +20 -0
  216. agentpool/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  217. agentpool/queries/tree-sitter-languages/julia-tags.scm +60 -0
  218. agentpool/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  219. agentpool/queries/tree-sitter-languages/matlab-tags.scm +10 -0
  220. agentpool/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  221. agentpool/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  222. agentpool/queries/tree-sitter-languages/php-tags.scm +26 -0
  223. agentpool/queries/tree-sitter-languages/python-tags.scm +12 -0
  224. agentpool/queries/tree-sitter-languages/ql-tags.scm +26 -0
  225. agentpool/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  226. agentpool/queries/tree-sitter-languages/rust-tags.scm +60 -0
  227. agentpool/queries/tree-sitter-languages/scala-tags.scm +65 -0
  228. agentpool/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  229. agentpool/queries/tree-sitter-languages/zig-tags.scm +3 -0
  230. agentpool/repomap.py +1231 -0
  231. agentpool/resource_providers/__init__.py +17 -0
  232. agentpool/resource_providers/aggregating.py +54 -0
  233. agentpool/resource_providers/base.py +172 -0
  234. agentpool/resource_providers/codemode/__init__.py +9 -0
  235. agentpool/resource_providers/codemode/code_executor.py +215 -0
  236. agentpool/resource_providers/codemode/default_prompt.py +19 -0
  237. agentpool/resource_providers/codemode/helpers.py +83 -0
  238. agentpool/resource_providers/codemode/progress_executor.py +212 -0
  239. agentpool/resource_providers/codemode/provider.py +150 -0
  240. agentpool/resource_providers/codemode/remote_mcp_execution.py +143 -0
  241. agentpool/resource_providers/codemode/remote_provider.py +171 -0
  242. agentpool/resource_providers/filtering.py +42 -0
  243. agentpool/resource_providers/mcp_provider.py +246 -0
  244. agentpool/resource_providers/plan_provider.py +196 -0
  245. agentpool/resource_providers/pool.py +69 -0
  246. agentpool/resource_providers/static.py +289 -0
  247. agentpool/running/__init__.py +20 -0
  248. agentpool/running/decorators.py +56 -0
  249. agentpool/running/discovery.py +101 -0
  250. agentpool/running/executor.py +284 -0
  251. agentpool/running/injection.py +111 -0
  252. agentpool/running/py.typed +0 -0
  253. agentpool/running/run_nodes.py +87 -0
  254. agentpool/server.py +122 -0
  255. agentpool/sessions/__init__.py +13 -0
  256. agentpool/sessions/manager.py +302 -0
  257. agentpool/sessions/models.py +71 -0
  258. agentpool/sessions/session.py +239 -0
  259. agentpool/sessions/store.py +163 -0
  260. agentpool/skills/__init__.py +5 -0
  261. agentpool/skills/manager.py +120 -0
  262. agentpool/skills/registry.py +210 -0
  263. agentpool/skills/skill.py +36 -0
  264. agentpool/storage/__init__.py +17 -0
  265. agentpool/storage/manager.py +419 -0
  266. agentpool/storage/serialization.py +136 -0
  267. agentpool/talk/__init__.py +13 -0
  268. agentpool/talk/registry.py +128 -0
  269. agentpool/talk/stats.py +159 -0
  270. agentpool/talk/talk.py +604 -0
  271. agentpool/tasks/__init__.py +20 -0
  272. agentpool/tasks/exceptions.py +25 -0
  273. agentpool/tasks/registry.py +33 -0
  274. agentpool/testing.py +129 -0
  275. agentpool/text_templates/__init__.py +39 -0
  276. agentpool/text_templates/system_prompt.jinja +30 -0
  277. agentpool/text_templates/tool_call_default.jinja +13 -0
  278. agentpool/text_templates/tool_call_markdown.jinja +25 -0
  279. agentpool/text_templates/tool_call_simple.jinja +5 -0
  280. agentpool/tools/__init__.py +16 -0
  281. agentpool/tools/base.py +269 -0
  282. agentpool/tools/exceptions.py +9 -0
  283. agentpool/tools/manager.py +255 -0
  284. agentpool/tools/tool_call_info.py +87 -0
  285. agentpool/ui/__init__.py +2 -0
  286. agentpool/ui/base.py +89 -0
  287. agentpool/ui/mock_provider.py +81 -0
  288. agentpool/ui/stdlib_provider.py +150 -0
  289. agentpool/utils/__init__.py +44 -0
  290. agentpool/utils/baseregistry.py +185 -0
  291. agentpool/utils/count_tokens.py +62 -0
  292. agentpool/utils/dag.py +184 -0
  293. agentpool/utils/importing.py +206 -0
  294. agentpool/utils/inspection.py +334 -0
  295. agentpool/utils/model_capabilities.py +25 -0
  296. agentpool/utils/network.py +28 -0
  297. agentpool/utils/now.py +22 -0
  298. agentpool/utils/parse_time.py +87 -0
  299. agentpool/utils/result_utils.py +35 -0
  300. agentpool/utils/signatures.py +305 -0
  301. agentpool/utils/streams.py +112 -0
  302. agentpool/utils/tasks.py +186 -0
  303. agentpool/vfs_registry.py +250 -0
  304. agentpool-2.1.9.dist-info/METADATA +336 -0
  305. agentpool-2.1.9.dist-info/RECORD +474 -0
  306. agentpool-2.1.9.dist-info/WHEEL +4 -0
  307. agentpool-2.1.9.dist-info/entry_points.txt +14 -0
  308. agentpool-2.1.9.dist-info/licenses/LICENSE +22 -0
  309. agentpool_cli/__init__.py +34 -0
  310. agentpool_cli/__main__.py +66 -0
  311. agentpool_cli/agent.py +175 -0
  312. agentpool_cli/cli_types.py +23 -0
  313. agentpool_cli/common.py +163 -0
  314. agentpool_cli/create.py +175 -0
  315. agentpool_cli/history.py +217 -0
  316. agentpool_cli/log.py +78 -0
  317. agentpool_cli/py.typed +0 -0
  318. agentpool_cli/run.py +84 -0
  319. agentpool_cli/serve_acp.py +177 -0
  320. agentpool_cli/serve_api.py +69 -0
  321. agentpool_cli/serve_mcp.py +74 -0
  322. agentpool_cli/serve_vercel.py +233 -0
  323. agentpool_cli/store.py +171 -0
  324. agentpool_cli/task.py +84 -0
  325. agentpool_cli/utils.py +104 -0
  326. agentpool_cli/watch.py +54 -0
  327. agentpool_commands/__init__.py +180 -0
  328. agentpool_commands/agents.py +199 -0
  329. agentpool_commands/base.py +45 -0
  330. agentpool_commands/commands.py +58 -0
  331. agentpool_commands/completers.py +110 -0
  332. agentpool_commands/connections.py +175 -0
  333. agentpool_commands/markdown_utils.py +31 -0
  334. agentpool_commands/models.py +62 -0
  335. agentpool_commands/prompts.py +78 -0
  336. agentpool_commands/py.typed +0 -0
  337. agentpool_commands/read.py +77 -0
  338. agentpool_commands/resources.py +210 -0
  339. agentpool_commands/session.py +48 -0
  340. agentpool_commands/tools.py +269 -0
  341. agentpool_commands/utils.py +189 -0
  342. agentpool_commands/workers.py +163 -0
  343. agentpool_config/__init__.py +53 -0
  344. agentpool_config/builtin_tools.py +265 -0
  345. agentpool_config/commands.py +237 -0
  346. agentpool_config/conditions.py +301 -0
  347. agentpool_config/converters.py +30 -0
  348. agentpool_config/durable.py +331 -0
  349. agentpool_config/event_handlers.py +600 -0
  350. agentpool_config/events.py +153 -0
  351. agentpool_config/forward_targets.py +251 -0
  352. agentpool_config/hook_conditions.py +331 -0
  353. agentpool_config/hooks.py +241 -0
  354. agentpool_config/jinja.py +206 -0
  355. agentpool_config/knowledge.py +41 -0
  356. agentpool_config/loaders.py +350 -0
  357. agentpool_config/mcp_server.py +243 -0
  358. agentpool_config/nodes.py +202 -0
  359. agentpool_config/observability.py +191 -0
  360. agentpool_config/output_types.py +55 -0
  361. agentpool_config/pool_server.py +267 -0
  362. agentpool_config/prompt_hubs.py +105 -0
  363. agentpool_config/prompts.py +185 -0
  364. agentpool_config/py.typed +0 -0
  365. agentpool_config/resources.py +33 -0
  366. agentpool_config/session.py +119 -0
  367. agentpool_config/skills.py +17 -0
  368. agentpool_config/storage.py +288 -0
  369. agentpool_config/system_prompts.py +190 -0
  370. agentpool_config/task.py +162 -0
  371. agentpool_config/teams.py +52 -0
  372. agentpool_config/tools.py +112 -0
  373. agentpool_config/toolsets.py +1033 -0
  374. agentpool_config/workers.py +86 -0
  375. agentpool_prompts/__init__.py +1 -0
  376. agentpool_prompts/braintrust_hub.py +235 -0
  377. agentpool_prompts/fabric.py +75 -0
  378. agentpool_prompts/langfuse_hub.py +79 -0
  379. agentpool_prompts/promptlayer_provider.py +59 -0
  380. agentpool_prompts/py.typed +0 -0
  381. agentpool_server/__init__.py +9 -0
  382. agentpool_server/a2a_server/__init__.py +5 -0
  383. agentpool_server/a2a_server/a2a_types.py +41 -0
  384. agentpool_server/a2a_server/server.py +190 -0
  385. agentpool_server/a2a_server/storage.py +81 -0
  386. agentpool_server/acp_server/__init__.py +22 -0
  387. agentpool_server/acp_server/acp_agent.py +786 -0
  388. agentpool_server/acp_server/acp_tools.py +43 -0
  389. agentpool_server/acp_server/commands/__init__.py +18 -0
  390. agentpool_server/acp_server/commands/acp_commands.py +594 -0
  391. agentpool_server/acp_server/commands/debug_commands.py +376 -0
  392. agentpool_server/acp_server/commands/docs_commands/__init__.py +39 -0
  393. agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +169 -0
  394. agentpool_server/acp_server/commands/docs_commands/get_schema.py +176 -0
  395. agentpool_server/acp_server/commands/docs_commands/get_source.py +110 -0
  396. agentpool_server/acp_server/commands/docs_commands/git_diff.py +111 -0
  397. agentpool_server/acp_server/commands/docs_commands/helpers.py +33 -0
  398. agentpool_server/acp_server/commands/docs_commands/url_to_markdown.py +90 -0
  399. agentpool_server/acp_server/commands/spawn.py +210 -0
  400. agentpool_server/acp_server/converters.py +235 -0
  401. agentpool_server/acp_server/input_provider.py +338 -0
  402. agentpool_server/acp_server/server.py +288 -0
  403. agentpool_server/acp_server/session.py +969 -0
  404. agentpool_server/acp_server/session_manager.py +313 -0
  405. agentpool_server/acp_server/syntax_detection.py +250 -0
  406. agentpool_server/acp_server/zed_tools.md +90 -0
  407. agentpool_server/aggregating_server.py +309 -0
  408. agentpool_server/agui_server/__init__.py +11 -0
  409. agentpool_server/agui_server/server.py +128 -0
  410. agentpool_server/base.py +189 -0
  411. agentpool_server/http_server.py +164 -0
  412. agentpool_server/mcp_server/__init__.py +6 -0
  413. agentpool_server/mcp_server/server.py +314 -0
  414. agentpool_server/mcp_server/zed_wrapper.py +110 -0
  415. agentpool_server/openai_api_server/__init__.py +5 -0
  416. agentpool_server/openai_api_server/completions/__init__.py +1 -0
  417. agentpool_server/openai_api_server/completions/helpers.py +81 -0
  418. agentpool_server/openai_api_server/completions/models.py +98 -0
  419. agentpool_server/openai_api_server/responses/__init__.py +1 -0
  420. agentpool_server/openai_api_server/responses/helpers.py +74 -0
  421. agentpool_server/openai_api_server/responses/models.py +96 -0
  422. agentpool_server/openai_api_server/server.py +242 -0
  423. agentpool_server/py.typed +0 -0
  424. agentpool_storage/__init__.py +9 -0
  425. agentpool_storage/base.py +310 -0
  426. agentpool_storage/file_provider.py +378 -0
  427. agentpool_storage/formatters.py +129 -0
  428. agentpool_storage/memory_provider.py +396 -0
  429. agentpool_storage/models.py +108 -0
  430. agentpool_storage/py.typed +0 -0
  431. agentpool_storage/session_store.py +262 -0
  432. agentpool_storage/sql_provider/__init__.py +21 -0
  433. agentpool_storage/sql_provider/cli.py +146 -0
  434. agentpool_storage/sql_provider/models.py +249 -0
  435. agentpool_storage/sql_provider/queries.py +15 -0
  436. agentpool_storage/sql_provider/sql_provider.py +444 -0
  437. agentpool_storage/sql_provider/utils.py +234 -0
  438. agentpool_storage/text_log_provider.py +275 -0
  439. agentpool_toolsets/__init__.py +15 -0
  440. agentpool_toolsets/builtin/__init__.py +33 -0
  441. agentpool_toolsets/builtin/agent_management.py +239 -0
  442. agentpool_toolsets/builtin/chain.py +288 -0
  443. agentpool_toolsets/builtin/code.py +398 -0
  444. agentpool_toolsets/builtin/debug.py +291 -0
  445. agentpool_toolsets/builtin/execution_environment.py +381 -0
  446. agentpool_toolsets/builtin/file_edit/__init__.py +11 -0
  447. agentpool_toolsets/builtin/file_edit/file_edit.py +747 -0
  448. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/__init__.py +5 -0
  449. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/example_usage.py +311 -0
  450. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/streaming_fuzzy_matcher.py +443 -0
  451. agentpool_toolsets/builtin/history.py +36 -0
  452. agentpool_toolsets/builtin/integration.py +85 -0
  453. agentpool_toolsets/builtin/skills.py +77 -0
  454. agentpool_toolsets/builtin/subagent_tools.py +324 -0
  455. agentpool_toolsets/builtin/tool_management.py +90 -0
  456. agentpool_toolsets/builtin/user_interaction.py +52 -0
  457. agentpool_toolsets/builtin/workers.py +128 -0
  458. agentpool_toolsets/composio_toolset.py +96 -0
  459. agentpool_toolsets/config_creation.py +192 -0
  460. agentpool_toolsets/entry_points.py +47 -0
  461. agentpool_toolsets/fsspec_toolset/__init__.py +7 -0
  462. agentpool_toolsets/fsspec_toolset/diagnostics.py +115 -0
  463. agentpool_toolsets/fsspec_toolset/grep.py +450 -0
  464. agentpool_toolsets/fsspec_toolset/helpers.py +631 -0
  465. agentpool_toolsets/fsspec_toolset/streaming_diff_parser.py +249 -0
  466. agentpool_toolsets/fsspec_toolset/toolset.py +1384 -0
  467. agentpool_toolsets/mcp_run_toolset.py +61 -0
  468. agentpool_toolsets/notifications.py +146 -0
  469. agentpool_toolsets/openapi.py +118 -0
  470. agentpool_toolsets/py.typed +0 -0
  471. agentpool_toolsets/search_toolset.py +202 -0
  472. agentpool_toolsets/semantic_memory_toolset.py +536 -0
  473. agentpool_toolsets/streaming_tools.py +265 -0
  474. agentpool_toolsets/vfs_toolset.py +124 -0
@@ -0,0 +1,325 @@
1
+ """Parallel, unordered group of agents / nodes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from time import perf_counter
7
+ from typing import TYPE_CHECKING, Any
8
+ from uuid import uuid4
9
+
10
+ from anyenv.async_run import as_generated
11
+ import anyio
12
+ from toprompt import to_prompt
13
+
14
+ from agentpool.common_types import SupportsRunStream
15
+ from agentpool.delegation.base_team import BaseTeam
16
+ from agentpool.log import get_logger
17
+ from agentpool.messaging import AgentResponse, ChatMessage, TeamResponse
18
+ from agentpool.messaging.processing import finalize_message, prepare_prompts
19
+ from agentpool.utils.now import get_now
20
+
21
+
22
+ logger = get_logger(__name__)
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import AsyncIterator
26
+
27
+ from toprompt import AnyPromptType
28
+
29
+ from agentpool import MessageNode
30
+ from agentpool.agents.events import RichAgentStreamEvent
31
+ from agentpool.common_types import PromptCompatible
32
+ from agentpool.talk import Talk
33
+ from agentpool_config.task import Job
34
+
35
+
36
+ async def normalize_stream_for_teams(
37
+ node: MessageNode[Any, Any],
38
+ *args: Any,
39
+ **kwargs: Any,
40
+ ) -> AsyncIterator[tuple[MessageNode[Any, Any], RichAgentStreamEvent[Any]]]:
41
+ """Normalize any streaming node to yield (node, event) tuples for team composition.
42
+
43
+ Args:
44
+ node: The streaming node (Agent, Team, etc.)
45
+ *args: Arguments to pass to run_stream
46
+ **kwargs: Keyword arguments to pass to run_stream
47
+
48
+ Yields:
49
+ Tuples of (node, event) where node is the MessageNode instance
50
+ and event is the streaming event from that node.
51
+ """
52
+ if not isinstance(node, SupportsRunStream):
53
+ msg = f"Node {node.name} does not support streaming"
54
+ raise TypeError(msg)
55
+
56
+ stream = node.run_stream(*args, **kwargs)
57
+ async for item in stream:
58
+ if isinstance(item, tuple):
59
+ # Already normalized (from Team or other composite node)
60
+ yield item
61
+ else:
62
+ # Raw event (from Agent) - wrap it with the source node
63
+ yield (node, item)
64
+
65
+
66
+ class Team[TDeps = None](BaseTeam[TDeps, Any]):
67
+ """Group of agents that can execute together."""
68
+
69
+ async def execute(self, *prompts: PromptCompatible | None, **kwargs: Any) -> TeamResponse:
70
+ """Run all agents in parallel with monitoring."""
71
+ from agentpool.talk.talk import Talk
72
+
73
+ self._team_talk.clear()
74
+ start_time = get_now()
75
+ responses: list[AgentResponse[Any]] = []
76
+ errors: dict[str, Exception] = {}
77
+ final_prompt = list(prompts)
78
+ if self.shared_prompt:
79
+ final_prompt.insert(0, self.shared_prompt)
80
+ combined_prompt = "\n".join([await to_prompt(p) for p in final_prompt])
81
+ all_nodes = list(await self.pick_agents(combined_prompt))
82
+ # Create Talk connections for monitoring this execution
83
+ execution_talks: list[Talk[Any]] = []
84
+ for node in all_nodes:
85
+ # No actual forwarding, just for tracking
86
+ talk = Talk[Any](node, [], connection_type="run", queued=True, queue_strategy="latest")
87
+ execution_talks.append(talk)
88
+ self._team_talk.append(talk) # Add to base class's TeamTalk
89
+
90
+ async def _run(node: MessageNode[TDeps, Any]) -> None:
91
+ try:
92
+ start = perf_counter()
93
+ message = await node.run(*final_prompt, **kwargs)
94
+ timing = perf_counter() - start
95
+ r = AgentResponse(agent_name=node.name, message=message, timing=timing)
96
+ responses.append(r)
97
+ # Update talk stats for this agent
98
+ talk = next(t for t in execution_talks if t.source == node)
99
+ talk._stats.messages.append(message)
100
+ except Exception as e: # noqa: BLE001
101
+ errors[node.name] = e
102
+
103
+ # Run all agents in parallel
104
+ await asyncio.gather(*[_run(node) for node in all_nodes])
105
+ return TeamResponse(responses=responses, start_time=start_time, errors=errors)
106
+
107
+ def __prompt__(self) -> str:
108
+ """Format team info for prompts."""
109
+ members = ", ".join(a.name for a in self.nodes)
110
+ desc = f" - {self.description}" if self.description else ""
111
+ return f"Parallel Team {self.name!r}{desc}\nMembers: {members}"
112
+
113
+ async def run_iter(
114
+ self,
115
+ *prompts: AnyPromptType,
116
+ **kwargs: Any,
117
+ ) -> AsyncIterator[ChatMessage[Any]]:
118
+ """Yield messages as they arrive from parallel execution."""
119
+ queue: asyncio.Queue[ChatMessage[Any] | None] = asyncio.Queue()
120
+ failures: dict[str, Exception] = {}
121
+
122
+ async def _run(node: MessageNode[TDeps, Any]) -> None:
123
+ try:
124
+ message = await node.run(*prompts, **kwargs)
125
+ await queue.put(message)
126
+ except Exception as e:
127
+ logger.exception("Error executing node", name=node.name)
128
+ failures[node.name] = e
129
+ # Put None to maintain queue count
130
+ await queue.put(None)
131
+
132
+ # Get nodes to run
133
+ combined_prompt = "\n".join([await to_prompt(p) for p in prompts])
134
+ all_nodes = list(await self.pick_agents(combined_prompt))
135
+
136
+ # Start all agents
137
+ tasks = [asyncio.create_task(_run(n), name=f"run_{n.name}") for n in all_nodes]
138
+
139
+ try:
140
+ # Yield messages as they arrive
141
+ for _ in all_nodes:
142
+ if msg := await queue.get():
143
+ yield msg
144
+
145
+ # If any failures occurred, raise error with details
146
+ if failures:
147
+ error_details = "\n".join(f"- {name}: {error}" for name, error in failures.items())
148
+ error_msg = f"Some nodes failed to execute:\n{error_details}"
149
+ raise RuntimeError(error_msg)
150
+
151
+ finally:
152
+ # Clean up any remaining tasks
153
+ for task in tasks:
154
+ if not task.done():
155
+ task.cancel()
156
+
157
+ async def run(
158
+ self,
159
+ *prompts: PromptCompatible | None,
160
+ wait_for_connections: bool | None = None,
161
+ store_history: bool = False,
162
+ **kwargs: Any,
163
+ ) -> ChatMessage[list[Any]]:
164
+ """Run all agents in parallel and return combined message."""
165
+ # Prepare prompts and create user message
166
+ user_msg, processed_prompts, original_message = await prepare_prompts(*prompts)
167
+ self.message_received.emit(user_msg)
168
+
169
+ # Execute team logic
170
+ result = await self.execute(*processed_prompts, **kwargs)
171
+ message_id = str(uuid4()) # Always generate unique response ID
172
+ message = ChatMessage(
173
+ content=[r.message.content for r in result if r.message],
174
+ messages=[m for r in result if r.message for m in r.message.messages],
175
+ role="assistant",
176
+ name=self.name,
177
+ message_id=message_id,
178
+ conversation_id=user_msg.conversation_id,
179
+ metadata={
180
+ "agent_names": [r.agent_name for r in result],
181
+ "errors": {name: str(error) for name, error in result.errors.items()},
182
+ "start_time": result.start_time.isoformat(),
183
+ },
184
+ )
185
+
186
+ # Teams typically don't store history by default, but allow it
187
+ if store_history:
188
+ # Teams could implement their own history management here if needed
189
+ pass
190
+
191
+ # Finalize and route message
192
+ return await finalize_message(
193
+ message,
194
+ user_msg,
195
+ self,
196
+ self.connections,
197
+ original_message,
198
+ wait_for_connections,
199
+ )
200
+
201
+ async def run_stream(
202
+ self,
203
+ *prompts: PromptCompatible,
204
+ **kwargs: Any,
205
+ ) -> AsyncIterator[tuple[MessageNode[Any, Any], RichAgentStreamEvent[Any]]]:
206
+ """Stream responses from all team members in parallel.
207
+
208
+ Args:
209
+ prompts: Input prompts to process in parallel
210
+ kwargs: Additional arguments passed to each agent
211
+
212
+ Yields:
213
+ Tuples of (agent, event) where agent is the Agent instance
214
+ and event is the streaming event from that agent.
215
+ """
216
+ # Get nodes to run
217
+ combined_prompt = "\n".join([await to_prompt(p) for p in prompts])
218
+ all_nodes = list(await self.pick_agents(combined_prompt))
219
+
220
+ # Create list of streams that yield (agent, event) tuples
221
+ agent_streams = [
222
+ normalize_stream_for_teams(agent, *prompts, **kwargs)
223
+ for agent in all_nodes
224
+ if isinstance(agent, SupportsRunStream)
225
+ ]
226
+
227
+ # Merge all agent streams
228
+ async for agent_event_tuple in as_generated(agent_streams):
229
+ yield agent_event_tuple
230
+
231
+ async def run_job[TJobResult](
232
+ self,
233
+ job: Job[TDeps, TJobResult],
234
+ *,
235
+ store_history: bool = True,
236
+ include_agent_tools: bool = True,
237
+ ) -> list[AgentResponse[TJobResult]]:
238
+ """Execute a job across all team members in parallel.
239
+
240
+ Args:
241
+ job: Job configuration to execute
242
+ store_history: Whether to add job execution to conversation history
243
+ include_agent_tools: Whether to include agent's tools alongside job tools
244
+
245
+ Returns:
246
+ List of responses from all agents
247
+
248
+ Raises:
249
+ JobError: If job execution fails for any agent
250
+ ValueError: If job configuration is invalid
251
+ """
252
+ from agentpool import Agent
253
+ from agentpool.tasks import JobError
254
+
255
+ responses: list[AgentResponse[TJobResult]] = []
256
+ errors: dict[str, Exception] = {}
257
+ start_time = get_now()
258
+
259
+ # Validate dependencies for all agents
260
+ if job.required_dependency is not None:
261
+ invalid_agents = [
262
+ agent.name
263
+ for agent in self.iter_agents()
264
+ if agent.deps_type is None
265
+ or not issubclass(agent.deps_type, job.required_dependency)
266
+ ]
267
+ if invalid_agents:
268
+ msg = (
269
+ f"Agents {', '.join(invalid_agents)} don't have required "
270
+ f"dependency type: {job.required_dependency}"
271
+ )
272
+ raise JobError(msg)
273
+
274
+ try:
275
+ # Load knowledge for all agents if provided
276
+ if job.knowledge:
277
+ # TODO: resources
278
+ tools = [t.name for t in job.get_tools()]
279
+ await self.distribute(content="", tools=tools)
280
+
281
+ prompt = await job.get_prompt()
282
+
283
+ async def _run(agent: MessageNode[TDeps, TJobResult]) -> None:
284
+ assert isinstance(agent, Agent)
285
+ try:
286
+ async with agent.tools.temporary_tools(
287
+ job.get_tools(), exclusive=not include_agent_tools
288
+ ):
289
+ start = perf_counter()
290
+ resp = AgentResponse(
291
+ agent_name=agent.name,
292
+ message=await agent.run(prompt, store_history=store_history),
293
+ timing=perf_counter() - start,
294
+ )
295
+ responses.append(resp)
296
+ except Exception as e: # noqa: BLE001
297
+ errors[agent.name] = e
298
+
299
+ # Run job in parallel on all agents
300
+ await asyncio.gather(*[_run(node) for node in self.nodes])
301
+ return TeamResponse(responses=responses, start_time=start_time, errors=errors)
302
+
303
+ except Exception as e:
304
+ msg = "Job execution failed"
305
+ logger.exception(msg)
306
+ raise JobError(msg) from e
307
+
308
+
309
+ if __name__ == "__main__":
310
+
311
+ async def main() -> None:
312
+ from agentpool import Agent, TeamRun
313
+
314
+ agent_a = Agent(name="A", model="test")
315
+ agent_b = Agent(name="B", model="test")
316
+ agent_c = Agent(name="C", model="test")
317
+ # Test Team containing TeamRun (parallel containing sequential)
318
+ inner_run = TeamRun([agent_a, agent_b], name="Sequential")
319
+ outer_team = Team([inner_run, agent_c], name="Parallel")
320
+
321
+ print("Testing Team containing TeamRun...")
322
+ async for node, event in outer_team.run_stream("test"):
323
+ print(f"{node.name}: {type(event).__name__}")
324
+
325
+ anyio.run(main)
@@ -0,0 +1,343 @@
1
+ """Sequential, ordered group of agents / nodes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from itertools import pairwise
7
+ from time import perf_counter
8
+ from typing import TYPE_CHECKING, Any, Literal, overload
9
+ from uuid import uuid4
10
+
11
+ import anyio
12
+ from pydantic_ai import PartDeltaEvent, TextPartDelta
13
+
14
+ from agentpool.common_types import SupportsRunStream
15
+ from agentpool.delegation.base_team import BaseTeam
16
+ from agentpool.delegation.team import normalize_stream_for_teams
17
+ from agentpool.log import get_logger
18
+ from agentpool.messaging import AgentResponse, ChatMessage, TeamResponse
19
+ from agentpool.messaging.processing import finalize_message, prepare_prompts
20
+ from agentpool.talk.talk import Talk, TeamTalk
21
+ from agentpool.utils.now import get_now
22
+
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import AsyncIterator, Sequence
26
+ from datetime import datetime
27
+
28
+ from agentpool import MessageNode
29
+ from agentpool.agents.events import RichAgentStreamEvent
30
+ from agentpool.common_types import PromptCompatible, SupportsStructuredOutput
31
+ from agentpool.delegation import AgentPool
32
+
33
+
34
+ logger = get_logger(__name__)
35
+
36
+ ResultMode = Literal["last", "concat"]
37
+
38
+
39
+ @dataclass(frozen=True, kw_only=True)
40
+ class ExtendedTeamTalk(TeamTalk):
41
+ """TeamTalk that also provides TeamRunStats interface."""
42
+
43
+ errors: list[tuple[str, str, datetime]] = field(default_factory=list)
44
+
45
+ def clear(self) -> None:
46
+ """Reset all tracking data."""
47
+ super().clear() # Clear base TeamTalk
48
+ self.errors.clear()
49
+
50
+ def add_error(self, agent: str, error: str) -> None:
51
+ """Track errors from AgentResponses."""
52
+ self.errors.append((agent, error, get_now()))
53
+
54
+
55
+ class TeamRun[TDeps, TResult](BaseTeam[TDeps, TResult]):
56
+ """Handles team operations with monitoring."""
57
+
58
+ @overload # validator set: it defines the output
59
+ def __init__(
60
+ self,
61
+ agents: Sequence[MessageNode[TDeps, Any]],
62
+ *,
63
+ name: str | None = None,
64
+ description: str | None = None,
65
+ display_name: str | None = None,
66
+ shared_prompt: str | None = None,
67
+ validator: MessageNode[Any, TResult],
68
+ picker: SupportsStructuredOutput | None = None,
69
+ num_picks: int | None = None,
70
+ pick_prompt: str | None = None,
71
+ agent_pool: AgentPool | None = None,
72
+ ) -> None: ...
73
+
74
+ @overload
75
+ def __init__( # no validator, but all nodes same output type.
76
+ self,
77
+ agents: Sequence[MessageNode[TDeps, TResult]],
78
+ *,
79
+ name: str | None = None,
80
+ description: str | None = None,
81
+ display_name: str | None = None,
82
+ shared_prompt: str | None = None,
83
+ validator: None = None,
84
+ picker: SupportsStructuredOutput | None = None,
85
+ num_picks: int | None = None,
86
+ pick_prompt: str | None = None,
87
+ agent_pool: AgentPool | None = None,
88
+ ) -> None: ...
89
+
90
+ @overload
91
+ def __init__(
92
+ self,
93
+ agents: Sequence[MessageNode[TDeps, Any]],
94
+ *,
95
+ name: str | None = None,
96
+ description: str | None = None,
97
+ display_name: str | None = None,
98
+ shared_prompt: str | None = None,
99
+ validator: MessageNode[Any, TResult] | None = None,
100
+ picker: SupportsStructuredOutput | None = None,
101
+ num_picks: int | None = None,
102
+ pick_prompt: str | None = None,
103
+ agent_pool: AgentPool | None = None,
104
+ ) -> None: ...
105
+
106
+ def __init__(
107
+ self,
108
+ agents: Sequence[MessageNode[TDeps, Any]],
109
+ *,
110
+ name: str | None = None,
111
+ description: str | None = None,
112
+ display_name: str | None = None,
113
+ shared_prompt: str | None = None,
114
+ validator: MessageNode[Any, TResult] | None = None,
115
+ picker: SupportsStructuredOutput | None = None,
116
+ num_picks: int | None = None,
117
+ pick_prompt: str | None = None,
118
+ agent_pool: AgentPool | None = None,
119
+ # result_mode: ResultMode = "last",
120
+ ) -> None:
121
+ super().__init__(
122
+ agents,
123
+ name=name,
124
+ description=description,
125
+ display_name=display_name,
126
+ shared_prompt=shared_prompt,
127
+ picker=picker,
128
+ num_picks=num_picks,
129
+ pick_prompt=pick_prompt,
130
+ agent_pool=agent_pool,
131
+ )
132
+ self.validator = validator
133
+ self.result_mode = "last"
134
+
135
+ def __prompt__(self) -> str:
136
+ """Format team info for prompts."""
137
+ members = " -> ".join(a.name for a in self.nodes)
138
+ desc = f" - {self.description}" if self.description else ""
139
+ return f"Sequential Team {self.name!r}{desc}\nPipeline: {members}"
140
+
141
+ async def run(
142
+ self,
143
+ *prompts: PromptCompatible | None,
144
+ wait_for_connections: bool | None = None,
145
+ store_history: bool = False,
146
+ **kwargs: Any,
147
+ ) -> ChatMessage[TResult]:
148
+ """Run agents sequentially and return combined message."""
149
+ # Prepare prompts and create user message
150
+ user_msg, processed_prompts, original_message = await prepare_prompts(*prompts)
151
+ self.message_received.emit(user_msg)
152
+ # Execute sequential logic
153
+ message_id = str(uuid4()) # Always generate unique response ID
154
+ result = await self.execute(*processed_prompts, **kwargs)
155
+ all_messages = [r.message for r in result if r.message]
156
+ assert all_messages, "Error during execution, returned None for TeamRun"
157
+ # Determine content based on mode
158
+ match self.result_mode:
159
+ case "last":
160
+ content = all_messages[-1].content
161
+ # case "concat":
162
+ # content = "\n".join(msg.format() for msg in all_messages)
163
+ case _:
164
+ msg = f"Invalid result mode: {self.result_mode}"
165
+ raise ValueError(msg)
166
+
167
+ message = ChatMessage(
168
+ content=content,
169
+ messages=[m for chat_message in all_messages for m in chat_message.messages],
170
+ role="assistant",
171
+ name=self.name,
172
+ associated_messages=all_messages,
173
+ message_id=message_id,
174
+ conversation_id=user_msg.conversation_id,
175
+ metadata={
176
+ "execution_order": [r.agent_name for r in result],
177
+ "start_time": result.start_time.isoformat(),
178
+ "errors": {name: str(error) for name, error in result.errors.items()},
179
+ },
180
+ )
181
+
182
+ if store_history:
183
+ pass # Teams could implement their own history management here if needed
184
+ return await finalize_message( # Finalize and route message
185
+ message,
186
+ user_msg,
187
+ self,
188
+ self.connections,
189
+ original_message,
190
+ wait_for_connections,
191
+ )
192
+
193
+ async def execute(
194
+ self,
195
+ *prompts: PromptCompatible | None,
196
+ **kwargs: Any,
197
+ ) -> TeamResponse[TResult]:
198
+ """Start execution with optional monitoring."""
199
+ self._team_talk.clear()
200
+ start_time = get_now()
201
+ prompts_ = list(prompts)
202
+ if self.shared_prompt:
203
+ prompts_.insert(0, self.shared_prompt)
204
+ responses = [i async for i in self.execute_iter(*prompts_) if isinstance(i, AgentResponse)]
205
+ return TeamResponse(responses, start_time)
206
+
207
+ async def run_iter(
208
+ self,
209
+ *prompts: PromptCompatible,
210
+ **kwargs: Any,
211
+ ) -> AsyncIterator[ChatMessage[Any]]:
212
+ """Yield messages from the execution chain."""
213
+ async for item in self.execute_iter(*prompts, **kwargs):
214
+ match item:
215
+ case AgentResponse():
216
+ if item.message:
217
+ yield item.message
218
+ case Talk():
219
+ pass
220
+
221
+ async def execute_iter(
222
+ self,
223
+ *prompt: PromptCompatible,
224
+ **kwargs: Any,
225
+ ) -> AsyncIterator[Talk[Any] | AgentResponse[Any]]:
226
+ from toprompt import to_prompt
227
+
228
+ connections: list[Talk[Any]] = []
229
+ try:
230
+ combined_prompt = "\n".join([await to_prompt(p) for p in prompt])
231
+ all_nodes = list(await self.pick_agents(combined_prompt))
232
+ if self.validator:
233
+ all_nodes.append(self.validator)
234
+ first = all_nodes[0]
235
+ connections = [s.connect_to(t, queued=True) for s, t in pairwise(all_nodes)]
236
+ for conn in connections:
237
+ self._team_talk.append(conn)
238
+
239
+ # First agent
240
+ start = perf_counter()
241
+ message = await first.run(*prompt, **kwargs)
242
+ timing = perf_counter() - start
243
+ response = AgentResponse[Any](first.name, message=message, timing=timing)
244
+ yield response
245
+
246
+ # Process through chain
247
+ for connection in connections:
248
+ target = connection.targets[0]
249
+ target_name = target.name
250
+ yield connection
251
+
252
+ # Let errors propagate - they break the chain
253
+ start = perf_counter()
254
+ messages = await connection.trigger()
255
+
256
+ if target == all_nodes[-1]:
257
+ last_talk = Talk[Any](target, [], connection_type="run")
258
+ if response.message:
259
+ last_talk.stats.messages.append(response.message)
260
+ self._team_talk.append(last_talk)
261
+
262
+ timing = perf_counter() - start
263
+ msg = messages[0]
264
+ response = AgentResponse[Any](target_name, message=msg, timing=timing)
265
+ yield response
266
+
267
+ finally: # Always clean up connections
268
+ for connection in connections:
269
+ connection.disconnect()
270
+
271
+ async def run_stream(
272
+ self,
273
+ *prompts: PromptCompatible,
274
+ require_all: bool = True,
275
+ **kwargs: Any,
276
+ ) -> AsyncIterator[tuple[MessageNode[Any, Any], RichAgentStreamEvent[Any]]]:
277
+ """Stream responses through the chain of team members.
278
+
279
+ Args:
280
+ prompts: Input prompts to process through the chain
281
+ require_all: If True, fail if any agent fails. If False,
282
+ continue with remaining agents.
283
+ kwargs: Additional arguments passed to each agent
284
+
285
+ Yields:
286
+ Tuples of (agent, event) where agent is the Agent instance
287
+ and event is the streaming event.
288
+ """
289
+ from agentpool.agents.events import StreamCompleteEvent
290
+
291
+ current_message = prompts
292
+ collected_content = []
293
+ for agent in self.nodes:
294
+ try:
295
+ agent_content = []
296
+
297
+ # Use wrapper to normalize all streaming nodes to (agent, event) tuples
298
+ if not isinstance(agent, SupportsRunStream):
299
+ msg = f"Agent {agent.name} does not support streaming"
300
+ raise TypeError(msg) # noqa: TRY301
301
+
302
+ stream = normalize_stream_for_teams(agent, *current_message, **kwargs)
303
+
304
+ async for agent_event_tuple in stream:
305
+ actual_agent, event = agent_event_tuple
306
+ match event:
307
+ case PartDeltaEvent(delta=TextPartDelta(content_delta=delta)):
308
+ agent_content.append(delta)
309
+ collected_content.append(delta)
310
+ yield (actual_agent, event) # Yield tuple with agent context
311
+ case StreamCompleteEvent(message=message):
312
+ # Use complete response as input for next agent
313
+ current_message = (message.content,)
314
+ yield (actual_agent, event) # Yield tuple with agent context
315
+ case _:
316
+ yield (actual_agent, event) # Yield tuple with agent context
317
+
318
+ except Exception as e:
319
+ if require_all:
320
+ msg = f"Chain broken at {agent.name}: {e}"
321
+ logger.exception(msg)
322
+ raise ValueError(msg) from e
323
+ logger.warning("Chain handler failed", name=agent.name, error=e)
324
+
325
+
326
+ if __name__ == "__main__":
327
+
328
+ async def main() -> None:
329
+ from agentpool import Agent, Team
330
+
331
+ agent1 = Agent(name="Agent1", model="test")
332
+ agent2 = Agent(name="Agent2", model="test")
333
+ agent3 = Agent(name="Agent3", model="test")
334
+ inner_team = Team([agent1, agent2], name="Parallel")
335
+ outer_run = TeamRun([inner_team, agent3], name="Sequential")
336
+ print("Testing TeamRun containing Team...")
337
+ try:
338
+ async for node, event in outer_run.run_stream("test"):
339
+ print(f"{node.name}: {type(event).__name__}")
340
+ except Exception as e: # noqa: BLE001
341
+ print(f"Error: {e}")
342
+
343
+ anyio.run(main)
@@ -0,0 +1,5 @@
1
+ """Example / Docs helpers."""
2
+
3
+ from agentpool.docs.utils import generate_tool_docs, tool_to_markdown
4
+
5
+ __all__ = ["generate_tool_docs", "tool_to_markdown"]