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,324 @@
1
+ """Provider for subagent interaction tools with streaming support."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any, Literal
6
+
7
+ from pydantic_ai import (
8
+ FunctionToolCallEvent,
9
+ FunctionToolResultEvent,
10
+ ModelRetry,
11
+ PartDeltaEvent,
12
+ PartStartEvent,
13
+ RetryPromptPart,
14
+ TextPart,
15
+ TextPartDelta,
16
+ ThinkingPart,
17
+ ThinkingPartDelta,
18
+ ToolCallPartDelta,
19
+ ToolReturnPart,
20
+ )
21
+
22
+ from agentpool.agents.context import AgentContext # noqa: TC001
23
+ from agentpool.log import get_logger
24
+ from agentpool.resource_providers import StaticResourceProvider
25
+ from agentpool.tools.exceptions import ToolError
26
+
27
+
28
+ if TYPE_CHECKING:
29
+ from collections.abc import AsyncIterator
30
+
31
+ from agentpool.agents.events import RichAgentStreamEvent
32
+
33
+
34
+ logger = get_logger(__name__)
35
+
36
+
37
+ # Delta type identifiers for batching
38
+ type _DeltaType = Literal["text", "thinking", "tool_call"] | None
39
+
40
+
41
+ async def batch_stream_deltas( # noqa: PLR0915
42
+ stream: AsyncIterator[RichAgentStreamEvent[Any]],
43
+ ) -> AsyncIterator[RichAgentStreamEvent[Any]]:
44
+ """Batch consecutive delta events, yielding when event type changes.
45
+
46
+ This reduces UI update frequency by accumulating consecutive deltas of the same
47
+ type and yielding them as a single event when the type changes.
48
+
49
+ Batches:
50
+ - TextPartDelta events (consecutive deltas combined into one)
51
+ - ThinkingPartDelta events (consecutive deltas combined into one)
52
+ - ToolCallPartDelta events (consecutive deltas combined into one)
53
+
54
+ All other events pass through immediately and flush any pending batch.
55
+ PartStartEvents pass through unchanged.
56
+
57
+ Args:
58
+ stream: Async iterator of stream events from agent.run_stream()
59
+
60
+ Yields:
61
+ Stream events with consecutive deltas batched together
62
+ """
63
+ pending_content: list[str] = []
64
+ pending_type: _DeltaType = None
65
+ pending_index: int = 0 # For PartDeltaEvent.index
66
+
67
+ def _make_batched_event() -> PartDeltaEvent:
68
+ """Create a synthetic PartDeltaEvent from accumulated content."""
69
+ content = "".join(pending_content)
70
+ delta: TextPartDelta | ThinkingPartDelta | ToolCallPartDelta
71
+ match pending_type:
72
+ case "text":
73
+ delta = TextPartDelta(content_delta=content)
74
+ case "thinking":
75
+ delta = ThinkingPartDelta(content_delta=content)
76
+ case "tool_call":
77
+ delta = ToolCallPartDelta(args_delta=content)
78
+ case _:
79
+ msg = f"Unexpected pending type: {pending_type}"
80
+ raise ValueError(msg)
81
+ return PartDeltaEvent(index=pending_index, delta=delta)
82
+
83
+ async for event in stream:
84
+ match event:
85
+ case PartDeltaEvent(delta=TextPartDelta(content_delta=content), index=idx):
86
+ if pending_type == "text":
87
+ pending_content.append(content)
88
+ else:
89
+ if pending_type is not None and pending_content:
90
+ yield _make_batched_event()
91
+ pending_content = [content]
92
+ pending_type = "text"
93
+ pending_index = idx
94
+
95
+ case PartDeltaEvent(delta=ThinkingPartDelta(content_delta=content), index=idx):
96
+ if content is None:
97
+ continue
98
+ if pending_type == "thinking":
99
+ pending_content.append(content)
100
+ else:
101
+ if pending_type is not None and pending_content:
102
+ yield _make_batched_event()
103
+ pending_content = [content]
104
+ pending_type = "thinking"
105
+ pending_index = idx
106
+
107
+ case PartDeltaEvent(delta=ToolCallPartDelta(args_delta=args), index=idx) if isinstance(
108
+ args, str
109
+ ):
110
+ if pending_type == "tool_call":
111
+ pending_content.append(args)
112
+ else:
113
+ if pending_type is not None and pending_content:
114
+ yield _make_batched_event()
115
+ pending_content = [args]
116
+ pending_type = "tool_call"
117
+ pending_index = idx
118
+
119
+ case _:
120
+ # Any other event: flush pending batch and pass through
121
+ if pending_type is not None and pending_content:
122
+ yield _make_batched_event()
123
+ pending_content = []
124
+ pending_type = None
125
+ yield event
126
+
127
+ # Flush any remaining batch at end of stream
128
+ if pending_type is not None and pending_content:
129
+ yield _make_batched_event()
130
+
131
+
132
+ async def _stream_agent_with_progress(
133
+ ctx: AgentContext,
134
+ stream: AsyncIterator[RichAgentStreamEvent[Any]],
135
+ *,
136
+ batch_deltas: bool = False,
137
+ ) -> str:
138
+ """Stream an agent's execution and emit progress events.
139
+
140
+ Args:
141
+ ctx: Agent context for emitting events
142
+ stream: Async iterator of stream events from agent.run_stream()
143
+ batch_deltas: If True, batch consecutive text/thinking deltas for fewer UI updates
144
+
145
+ Returns:
146
+ Aggregated content from the stream
147
+ """
148
+ if batch_deltas:
149
+ stream = batch_stream_deltas(stream)
150
+
151
+ aggregated: list[str] = []
152
+ async for event in stream:
153
+ match event:
154
+ case (
155
+ PartStartEvent(part=TextPart(content=delta))
156
+ | PartDeltaEvent(delta=TextPartDelta(content_delta=delta))
157
+ ):
158
+ aggregated.append(delta)
159
+ await ctx.events.tool_call_progress("".join(aggregated))
160
+ case (
161
+ PartStartEvent(part=ThinkingPart(content=delta))
162
+ | PartDeltaEvent(delta=ThinkingPartDelta(content_delta=delta))
163
+ ):
164
+ if delta:
165
+ aggregated.append(f"💭 {delta}")
166
+ await ctx.events.tool_call_progress("".join(aggregated))
167
+ case FunctionToolCallEvent(part=part):
168
+ aggregated.append(f"\n🔧 Using tool: {part.tool_name}\n")
169
+ await ctx.events.tool_call_progress("".join(aggregated))
170
+ case FunctionToolResultEvent(
171
+ result=ToolReturnPart(content=content, tool_name=tool_name),
172
+ ):
173
+ aggregated.append(f"✅ {tool_name}: {content}\n")
174
+ await ctx.events.tool_call_progress("".join(aggregated))
175
+
176
+ case FunctionToolResultEvent(result=RetryPromptPart(tool_name=tool_name) as result):
177
+ error_message = result.model_response()
178
+ aggregated.append(f"❌ {tool_name or 'unknown'}: {error_message}\n")
179
+ await ctx.events.tool_call_progress("".join(aggregated))
180
+ case _:
181
+ pass
182
+
183
+ return "".join(aggregated).strip()
184
+
185
+
186
+ class SubagentTools(StaticResourceProvider):
187
+ """Provider for subagent interaction tools with streaming progress."""
188
+
189
+ def __init__(
190
+ self,
191
+ name: str = "subagent_tools",
192
+ *,
193
+ batch_stream_deltas: bool = False,
194
+ ) -> None:
195
+ super().__init__(name=name)
196
+ self._batch_stream_deltas = batch_stream_deltas
197
+ for tool in [
198
+ self.create_tool(
199
+ self.list_available_nodes, category="search", read_only=True, idempotent=True
200
+ ),
201
+ self.create_tool(self.delegate_to, category="other"),
202
+ self.create_tool(self.ask_agent, category="other"),
203
+ ]:
204
+ self.add_tool(tool)
205
+
206
+ async def list_available_nodes( # noqa: D417
207
+ self,
208
+ ctx: AgentContext,
209
+ node_type: Literal["all", "agent", "team"] = "all",
210
+ only_idle: bool = False,
211
+ ) -> str:
212
+ """List available agents and/or teams in the current pool.
213
+
214
+ Args:
215
+ node_type: Filter by node type - "all", "agent", or "team"
216
+ only_idle: If True, only returns nodes that aren't currently busy
217
+
218
+ Returns:
219
+ List of node names that you can use with delegate_to or ask_agent
220
+ """
221
+ from agentpool import Agent
222
+
223
+ if not ctx.pool:
224
+ msg = "No agent pool available"
225
+ raise ToolError(msg)
226
+ lines: list[str] = []
227
+ if node_type in ("all", "agent"):
228
+ agents = dict(ctx.pool.all_agents)
229
+ if only_idle:
230
+ agents = {
231
+ n: a for n, a in agents.items() if not (isinstance(a, Agent) and a.is_busy())
232
+ }
233
+ for name, agent in agents.items():
234
+ lines.extend([
235
+ f"name: {name}",
236
+ "type: agent",
237
+ f"description: {agent.description or 'No description'}",
238
+ "---",
239
+ ])
240
+
241
+ if node_type in ("all", "team"): # List teams
242
+ teams = ctx.pool.teams
243
+ if only_idle:
244
+ teams = {name: team for name, team in teams.items() if not team.is_running}
245
+ for name, team in teams.items():
246
+ lines.extend([
247
+ f"name: {name}",
248
+ f"description: {team.description or 'No description'}",
249
+ "---",
250
+ ])
251
+
252
+ return "\n".join(lines) if lines else "No nodes available"
253
+
254
+ async def delegate_to( # noqa: D417
255
+ self,
256
+ ctx: AgentContext,
257
+ agent_or_team_name: str,
258
+ prompt: str,
259
+ ) -> str:
260
+ """Delegate a task to an agent or team.
261
+
262
+ If an action requires you to delegate a task, this tool can be used to assign and
263
+ execute a task. Instructions can be passed via the prompt parameter.
264
+
265
+ Args:
266
+ agent_or_team_name: The agent or team to delegate the task to
267
+ prompt: Instructions for the agent or team to delegate to.
268
+
269
+ Returns:
270
+ The result of the delegated task
271
+ """
272
+ if not ctx.pool:
273
+ msg = "Agent needs to be in a pool to delegate tasks"
274
+ raise ToolError(msg)
275
+ if agent_or_team_name not in ctx.pool.nodes:
276
+ msg = (
277
+ f"No agent or team found with name: {agent_or_team_name}. "
278
+ f"Available nodes: {', '.join(ctx.pool.nodes.keys())}"
279
+ )
280
+ raise ModelRetry(msg)
281
+
282
+ # For teams, use simple run() - no streaming support yet
283
+ if agent_or_team_name in ctx.pool.teams:
284
+ result = await ctx.pool.teams[agent_or_team_name].run(prompt)
285
+ return result.format(style="detailed", show_costs=True)
286
+ # For agents (regular or ACP), stream with progress events
287
+ agent = ctx.pool.all_agents[agent_or_team_name]
288
+ return await _stream_agent_with_progress(
289
+ ctx, agent.run_stream(prompt), batch_deltas=self._batch_stream_deltas
290
+ )
291
+
292
+ async def ask_agent( # noqa: D417
293
+ self,
294
+ ctx: AgentContext,
295
+ agent_name: str,
296
+ message: str,
297
+ ) -> str:
298
+ """Send a message to a specific agent and get their response.
299
+
300
+ Args:
301
+ agent_name: Name of the agent to interact with
302
+ message: Message to send to the agent
303
+
304
+ Returns:
305
+ The agent's response
306
+ """
307
+ if not ctx.pool:
308
+ msg = "No agent pool available"
309
+ raise ToolError(msg)
310
+
311
+ if agent_name not in ctx.pool.all_agents:
312
+ available = list(ctx.pool.all_agents.keys())
313
+ names = ", ".join(available)
314
+ raise ModelRetry(f"Agent not found: {agent_name}. Available agents: {names}")
315
+
316
+ agent = ctx.pool.all_agents[agent_name]
317
+ try:
318
+ stream = agent.run_stream(message)
319
+ return await _stream_agent_with_progress(
320
+ ctx, stream, batch_deltas=self._batch_stream_deltas
321
+ )
322
+ except Exception as e:
323
+ msg = f"Failed to ask agent {agent_name}: {e}"
324
+ raise ModelRetry(msg) from e
@@ -0,0 +1,90 @@
1
+ """Provider for tool management tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from agentpool.agents.context import AgentContext # noqa: TC001
8
+ from agentpool.resource_providers import StaticResourceProvider
9
+ from agentpool.tools.base import Tool
10
+
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+
15
+
16
+ async def register_tool( # noqa: D417
17
+ ctx: AgentContext,
18
+ tool: str | Callable[..., Any],
19
+ name: str | None = None,
20
+ description: str | None = None,
21
+ enabled: bool = True,
22
+ ) -> str:
23
+ """Register a new tool from callable or import path.
24
+
25
+ Args:
26
+ tool: Callable function or import path string to register as tool
27
+ name: Optional name override for the tool
28
+ description: Optional description override for the tool
29
+ enabled: Whether the tool should be enabled initially
30
+
31
+ Returns:
32
+ Confirmation message with registered tool name
33
+ """
34
+ # Create tool from callable/import path
35
+ tool_obj = Tool.from_callable(
36
+ tool,
37
+ name_override=name,
38
+ description_override=description,
39
+ source="dynamic",
40
+ enabled=enabled,
41
+ )
42
+
43
+ # Register with the agent's tool manager
44
+ registered_tool = ctx.agent.tools.register_tool(tool_obj)
45
+
46
+ return f"Successfully registered tool: {registered_tool.name}"
47
+
48
+
49
+ async def register_code_tool( # noqa: D417
50
+ ctx: AgentContext,
51
+ code: str,
52
+ name: str | None = None,
53
+ description: str | None = None,
54
+ enabled: bool = True,
55
+ ) -> str:
56
+ """Register a new tool from code string.
57
+
58
+ Args:
59
+ code: Python code string containing a callable function
60
+ name: Optional name override for the tool
61
+ description: Optional description override for the tool
62
+ enabled: Whether the tool should be enabled initially
63
+
64
+ Returns:
65
+ Confirmation message with registered tool name
66
+ """
67
+ # Create tool from code
68
+ tool_obj = Tool.from_code(
69
+ code,
70
+ name=name,
71
+ description=description,
72
+ )
73
+ tool_obj.enabled = enabled
74
+ tool_obj.source = "dynamic"
75
+
76
+ # Register with the agent's tool manager
77
+ registered_tool = ctx.agent.tools.register_tool(tool_obj)
78
+
79
+ return f"Successfully registered code tool: {registered_tool.name}"
80
+
81
+
82
+ class ToolManagementTools(StaticResourceProvider):
83
+ """Provider for tool management tools."""
84
+
85
+ def __init__(self, name: str = "tool_management") -> None:
86
+ super().__init__(name=name)
87
+ self._tools = [
88
+ self.create_tool(register_tool, category="other"),
89
+ self.create_tool(register_code_tool, category="other"),
90
+ ]
@@ -0,0 +1,52 @@
1
+ """Provider for user interaction tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, assert_never
6
+
7
+ from agentpool.agents.context import AgentContext # noqa: TC001
8
+ from agentpool.resource_providers import StaticResourceProvider
9
+
10
+
11
+ async def ask_user( # noqa: D417
12
+ ctx: AgentContext,
13
+ prompt: str,
14
+ response_schema: dict[str, Any] | None = None,
15
+ ) -> str:
16
+ """Allow LLM to ask user a clarifying question during processing.
17
+
18
+ This tool enables agents to ask users for additional information or clarification
19
+ when needed to complete a task effectively.
20
+
21
+ Args:
22
+ prompt: Question to ask the user
23
+ response_schema: Optional JSON schema for structured response (defaults to string)
24
+
25
+ Returns:
26
+ The user's response as a string
27
+ """
28
+ from mcp.types import ElicitRequestFormParams, ElicitResult, ErrorData
29
+
30
+ schema = response_schema or {"type": "string"} # string schema if no none provided
31
+ params = ElicitRequestFormParams(message=prompt, requestedSchema=schema)
32
+ result = await ctx.handle_elicitation(params)
33
+
34
+ match result:
35
+ case ElicitResult(action="accept", content=content):
36
+ return str(content)
37
+ case ElicitResult(action="cancel"):
38
+ return "User cancelled the request"
39
+ case ElicitResult():
40
+ return "User declined to answer"
41
+ case ErrorData(message=message):
42
+ return f"Error: {message}"
43
+ case _ as unreachable:
44
+ assert_never(unreachable)
45
+
46
+
47
+ class UserInteractionTools(StaticResourceProvider):
48
+ """Provider for user interaction tools."""
49
+
50
+ def __init__(self, name: str = "user_interaction") -> None:
51
+ super().__init__(name=name)
52
+ self._tools = [self.create_tool(ask_user, category="other", open_world=True)]
@@ -0,0 +1,128 @@
1
+ """Provider for worker agent tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from agentpool.agents.context import AgentContext # noqa: TC001
8
+ from agentpool.log import get_logger
9
+ from agentpool.resource_providers import ResourceProvider
10
+ from agentpool.tools.exceptions import ToolError
11
+
12
+
13
+ if TYPE_CHECKING:
14
+ from agentpool.tools.base import Tool
15
+ from agentpool_config.workers import WorkerConfig
16
+
17
+ logger = get_logger(__name__)
18
+
19
+
20
+ class WorkersTools(ResourceProvider):
21
+ """Provider for worker agent tools.
22
+
23
+ Creates tools for each configured worker that delegate to agents/teams in the pool.
24
+ Tools are created lazily when get_tools() is called, using AgentContext to access
25
+ the pool at call time.
26
+ """
27
+
28
+ def __init__(self, workers: list[WorkerConfig], name: str = "workers") -> None:
29
+ """Initialize workers toolset.
30
+
31
+ Args:
32
+ workers: List of worker configurations
33
+ name: Provider name
34
+ """
35
+ super().__init__(name=name)
36
+ self.workers = workers
37
+
38
+ async def get_tools(self) -> list[Tool]:
39
+ """Get tools for all configured workers."""
40
+ return [self._create_worker_tool(i) for i in self.workers]
41
+
42
+ def _create_worker_tool(self, worker_config: WorkerConfig) -> Tool:
43
+ """Create a tool for a single worker configuration."""
44
+ from agentpool_config.workers import AgentWorkerConfig
45
+
46
+ worker_name = worker_config.name
47
+ # Regular agents get history management
48
+ if isinstance(worker_config, AgentWorkerConfig):
49
+ return self._create_agent_tool(
50
+ worker_name,
51
+ reset_history_on_run=worker_config.reset_history_on_run,
52
+ pass_message_history=worker_config.pass_message_history,
53
+ )
54
+ # Teams, ACP agents, AGUI agents - all handled uniformly
55
+ return self._create_node_tool(worker_name)
56
+
57
+ def _create_agent_tool(
58
+ self,
59
+ agent_name: str,
60
+ *,
61
+ reset_history_on_run: bool = True,
62
+ pass_message_history: bool = False,
63
+ ) -> Tool:
64
+ """Create tool for a regular agent worker with history management."""
65
+
66
+ async def run(ctx: AgentContext, prompt: str) -> Any:
67
+ if not ctx.pool:
68
+ msg = "No agent pool available"
69
+ raise ToolError(msg)
70
+ if agent_name not in ctx.pool.agents:
71
+ msg = f"Agent {agent_name!r} not found in pool"
72
+ raise ToolError(msg)
73
+
74
+ worker = ctx.pool.agents[agent_name]
75
+ old_history = None
76
+
77
+ if pass_message_history:
78
+ old_history = worker.conversation.get_history()
79
+ worker.conversation.set_history(ctx.agent.conversation.get_history())
80
+ elif reset_history_on_run:
81
+ worker.conversation.clear()
82
+
83
+ try:
84
+ result = await worker.run(prompt)
85
+ return result.data
86
+ finally:
87
+ if old_history is not None:
88
+ worker.conversation.set_history(old_history)
89
+
90
+ tool_name = f"ask_{agent_name}"
91
+ normalized_name = agent_name.replace("_", " ").title()
92
+ docstring = f"Get expert answer from specialized agent: {normalized_name}"
93
+
94
+ run.__name__ = tool_name
95
+ run.__doc__ = docstring
96
+
97
+ return self.create_tool(run, name_override=tool_name, description_override=docstring)
98
+
99
+ def _create_node_tool(self, node_name: str) -> Tool:
100
+ """Create tool for non-agent nodes (teams, ACP agents, AGUI agents)."""
101
+ from agentpool import BaseTeam
102
+
103
+ async def run(ctx: AgentContext, prompt: str) -> str:
104
+ if not ctx.pool:
105
+ msg = "No agent pool available"
106
+ raise ToolError(msg)
107
+ if node_name not in ctx.pool.nodes:
108
+ msg = f"Worker {node_name!r} not found in pool"
109
+ raise ToolError(msg)
110
+
111
+ worker = ctx.pool.nodes[node_name]
112
+ result = await worker.run(prompt)
113
+
114
+ # Teams get formatted output
115
+ if isinstance(worker, BaseTeam):
116
+ return result.format(style="detailed", show_costs=True)
117
+
118
+ # Other nodes (ACP, AGUI) just return data as string
119
+ return str(result.data)
120
+
121
+ tool_name = f"ask_{node_name}"
122
+ normalized_name = node_name.replace("_", " ").title()
123
+ docstring = f"Delegate task to worker: {normalized_name}"
124
+
125
+ run.__name__ = tool_name
126
+ run.__doc__ = docstring
127
+
128
+ return self.create_tool(run, name_override=tool_name, description_override=docstring)
@@ -0,0 +1,96 @@
1
+ """Composio based toolset implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ from agentpool.log import get_logger
9
+ from agentpool.resource_providers import ResourceProvider
10
+
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+
15
+ from agentpool.tools.base import Tool
16
+
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ class ComposioTools(ResourceProvider):
22
+ """Provider for composio tools."""
23
+
24
+ def __init__(self, user_id: str, toolsets: list[str], api_key: str | None = None) -> None:
25
+ from composio import Composio
26
+ from composio.core.provider._openai import OpenAIProvider
27
+
28
+ super().__init__(name=f"composio_{user_id}")
29
+ self.user_id = user_id
30
+ key = api_key or os.environ.get("COMPOSIO_API_KEY")
31
+ if key:
32
+ self.composio = Composio[OpenAIProvider](api_key=key)
33
+ else:
34
+ self.composio = Composio[OpenAIProvider]()
35
+ self._tools: list[Tool] | None = None
36
+ self._toolkits = toolsets
37
+
38
+ def _create_tool_handler(self, tool_slug: str) -> Callable[..., Any]:
39
+ """Create a handler function for a specific tool."""
40
+
41
+ def handle_tool_call(**kwargs: Any) -> Any:
42
+ try:
43
+ return self.composio.tools.execute(
44
+ slug=tool_slug,
45
+ arguments=kwargs,
46
+ user_id=self.user_id,
47
+ )
48
+ except Exception:
49
+ logger.exception("Error executing tool", name=tool_slug)
50
+ return {"error": f"Failed to execute tool {tool_slug}"}
51
+
52
+ handle_tool_call.__name__ = tool_slug
53
+ return handle_tool_call
54
+
55
+ async def get_tools(self) -> list[Tool]:
56
+ """Get tools from composio."""
57
+ # Return cached tools if available
58
+ if self._tools is not None:
59
+ return self._tools
60
+
61
+ self._tools = []
62
+
63
+ try:
64
+ # Get tools for GitHub toolkit using v3 API
65
+ tools = self.composio.tools.get(self.user_id, toolkits=self._toolkits)
66
+
67
+ for tool_def in tools:
68
+ # In v3 SDK, tools are OpenAI formatted by default
69
+ if isinstance(tool_def, dict) and "function" in tool_def:
70
+ tool_slug = tool_def["function"].get("name", "")
71
+ if tool_slug:
72
+ fn = self._create_tool_handler(tool_slug)
73
+ tool = self.create_tool(fn, schema_override=tool_def["function"])
74
+ self._tools.append(tool)
75
+
76
+ except Exception:
77
+ logger.exception("Error getting Composio tools")
78
+ # Return empty list if there's an error
79
+ self._tools = []
80
+
81
+ return self._tools
82
+
83
+
84
+ if __name__ == "__main__":
85
+ import anyio
86
+
87
+ async def main() -> None:
88
+ from agentpool import Agent
89
+
90
+ tools = ComposioTools("user@example.com", toolsets=["github"])
91
+ agent = Agent(model="gpt-5-nano")
92
+ agent.tools.add_provider(tools)
93
+ result = await agent.run("tell me the tools at your disposal")
94
+ print(result)
95
+
96
+ anyio.run(main)