agno 2.2.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,702 @@
1
+ import inspect
2
+ from dataclasses import dataclass
3
+ from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Iterator, List, Optional, Union
4
+ from uuid import uuid4
5
+
6
+ from agno.run.agent import RunOutputEvent
7
+ from agno.run.base import RunContext
8
+ from agno.run.team import TeamRunOutputEvent
9
+ from agno.run.workflow import (
10
+ RouterExecutionCompletedEvent,
11
+ RouterExecutionStartedEvent,
12
+ WorkflowRunOutput,
13
+ WorkflowRunOutputEvent,
14
+ )
15
+ from agno.session.workflow import WorkflowSession
16
+ from agno.utils.log import log_debug, logger
17
+ from agno.workflow.step import Step
18
+ from agno.workflow.types import StepInput, StepOutput, StepType
19
+
20
+ WorkflowSteps = List[
21
+ Union[
22
+ Callable[
23
+ [StepInput], Union[StepOutput, Awaitable[StepOutput], Iterator[StepOutput], AsyncIterator[StepOutput]]
24
+ ],
25
+ Step,
26
+ "Steps", # type: ignore # noqa: F821
27
+ "Loop", # type: ignore # noqa: F821
28
+ "Parallel", # type: ignore # noqa: F821
29
+ "Condition", # type: ignore # noqa: F821
30
+ "Router", # type: ignore # noqa: F821
31
+ ]
32
+ ]
33
+
34
+
35
+ @dataclass
36
+ class Router:
37
+ """A router that dynamically selects which step(s) to execute based on input"""
38
+
39
+ # Router function that returns the step(s) to execute
40
+ selector: Union[
41
+ Callable[[StepInput], Union[WorkflowSteps, List[WorkflowSteps]]],
42
+ Callable[[StepInput], Awaitable[Union[WorkflowSteps, List[WorkflowSteps]]]],
43
+ ]
44
+ choices: WorkflowSteps # Available steps that can be selected
45
+
46
+ name: Optional[str] = None
47
+ description: Optional[str] = None
48
+
49
+ def _prepare_steps(self):
50
+ """Prepare the steps for execution - mirrors workflow logic"""
51
+ from agno.agent.agent import Agent
52
+ from agno.team.team import Team
53
+ from agno.workflow.condition import Condition
54
+ from agno.workflow.loop import Loop
55
+ from agno.workflow.parallel import Parallel
56
+ from agno.workflow.step import Step
57
+ from agno.workflow.steps import Steps
58
+
59
+ prepared_steps: WorkflowSteps = []
60
+ for step in self.choices:
61
+ if callable(step) and hasattr(step, "__name__"):
62
+ prepared_steps.append(Step(name=step.__name__, description="User-defined callable step", executor=step))
63
+ elif isinstance(step, Agent):
64
+ prepared_steps.append(Step(name=step.name, description=step.description, agent=step))
65
+ elif isinstance(step, Team):
66
+ prepared_steps.append(Step(name=step.name, description=step.description, team=step))
67
+ elif isinstance(step, (Step, Steps, Loop, Parallel, Condition, Router)):
68
+ prepared_steps.append(step)
69
+ else:
70
+ raise ValueError(f"Invalid step type: {type(step).__name__}")
71
+
72
+ self.steps = prepared_steps
73
+
74
+ def _update_step_input_from_outputs(
75
+ self,
76
+ step_input: StepInput,
77
+ step_outputs: Union[StepOutput, List[StepOutput]],
78
+ router_step_outputs: Optional[Dict[str, StepOutput]] = None,
79
+ ) -> StepInput:
80
+ """Helper to update step input from step outputs - mirrors Loop logic"""
81
+ current_images = step_input.images or []
82
+ current_videos = step_input.videos or []
83
+ current_audio = step_input.audio or []
84
+
85
+ if isinstance(step_outputs, list):
86
+ all_images = sum([out.images or [] for out in step_outputs], [])
87
+ all_videos = sum([out.videos or [] for out in step_outputs], [])
88
+ all_audio = sum([out.audio or [] for out in step_outputs], [])
89
+ previous_step_content = step_outputs[-1].content if step_outputs else None
90
+ else:
91
+ all_images = step_outputs.images or []
92
+ all_videos = step_outputs.videos or []
93
+ all_audio = step_outputs.audio or []
94
+ previous_step_content = step_outputs.content
95
+
96
+ updated_previous_step_outputs = {}
97
+ if step_input.previous_step_outputs:
98
+ updated_previous_step_outputs.update(step_input.previous_step_outputs)
99
+ if router_step_outputs:
100
+ updated_previous_step_outputs.update(router_step_outputs)
101
+
102
+ return StepInput(
103
+ input=step_input.input,
104
+ previous_step_content=previous_step_content,
105
+ previous_step_outputs=updated_previous_step_outputs,
106
+ additional_data=step_input.additional_data,
107
+ images=current_images + all_images,
108
+ videos=current_videos + all_videos,
109
+ audio=current_audio + all_audio,
110
+ )
111
+
112
+ def _route_steps(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> List[Step]: # type: ignore[return-value]
113
+ """Route to the appropriate steps based on input"""
114
+ if callable(self.selector):
115
+ if session_state is not None and self._selector_has_session_state_param():
116
+ result = self.selector(step_input, session_state) # type: ignore[call-arg]
117
+ else:
118
+ result = self.selector(step_input)
119
+
120
+ # Handle the result based on its type
121
+ if isinstance(result, Step):
122
+ return [result]
123
+ elif isinstance(result, list):
124
+ return result # type: ignore
125
+ else:
126
+ logger.warning(f"Router function returned unexpected type: {type(result)}")
127
+ return []
128
+
129
+ return []
130
+
131
+ async def _aroute_steps(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> List[Step]: # type: ignore[return-value]
132
+ """Async version of step routing"""
133
+ if callable(self.selector):
134
+ has_session_state = session_state is not None and self._selector_has_session_state_param()
135
+
136
+ if inspect.iscoroutinefunction(self.selector):
137
+ if has_session_state:
138
+ result = await self.selector(step_input, session_state) # type: ignore[call-arg]
139
+ else:
140
+ result = await self.selector(step_input)
141
+ else:
142
+ if has_session_state:
143
+ result = self.selector(step_input, session_state) # type: ignore[call-arg]
144
+ else:
145
+ result = self.selector(step_input)
146
+
147
+ # Handle the result based on its type
148
+ if isinstance(result, Step):
149
+ return [result]
150
+ elif isinstance(result, list):
151
+ return result
152
+ else:
153
+ logger.warning(f"Router function returned unexpected type: {type(result)}")
154
+ return []
155
+
156
+ return []
157
+
158
+ def _selector_has_session_state_param(self) -> bool:
159
+ """Check if the selector function has a session_state parameter"""
160
+ if not callable(self.selector):
161
+ return False
162
+
163
+ try:
164
+ sig = inspect.signature(self.selector)
165
+ return "session_state" in sig.parameters
166
+ except Exception:
167
+ return False
168
+
169
+ def execute(
170
+ self,
171
+ step_input: StepInput,
172
+ session_id: Optional[str] = None,
173
+ user_id: Optional[str] = None,
174
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
175
+ run_context: Optional[RunContext] = None,
176
+ session_state: Optional[Dict[str, Any]] = None,
177
+ store_executor_outputs: bool = True,
178
+ workflow_session: Optional[WorkflowSession] = None,
179
+ add_workflow_history_to_steps: Optional[bool] = False,
180
+ num_history_runs: int = 3,
181
+ ) -> StepOutput:
182
+ """Execute the router and its selected steps with sequential chaining"""
183
+ log_debug(f"Router Start: {self.name}", center=True, symbol="-")
184
+
185
+ router_step_id = str(uuid4())
186
+
187
+ self._prepare_steps()
188
+
189
+ # Route to appropriate steps
190
+ if run_context is not None and run_context.session_state is not None:
191
+ steps_to_execute = self._route_steps(step_input, session_state=run_context.session_state)
192
+ else:
193
+ steps_to_execute = self._route_steps(step_input, session_state=session_state)
194
+ log_debug(f"Router {self.name}: Selected {len(steps_to_execute)} steps to execute")
195
+
196
+ if not steps_to_execute:
197
+ return StepOutput(
198
+ step_name=self.name,
199
+ step_id=router_step_id,
200
+ step_type=StepType.ROUTER,
201
+ content=f"Router {self.name} completed with 0 results (no steps selected)",
202
+ success=True,
203
+ )
204
+
205
+ all_results: List[StepOutput] = []
206
+ current_step_input = step_input
207
+ router_step_outputs = {}
208
+
209
+ for i, step in enumerate(steps_to_execute):
210
+ try:
211
+ step_output = step.execute(
212
+ current_step_input,
213
+ session_id=session_id,
214
+ user_id=user_id,
215
+ workflow_run_response=workflow_run_response,
216
+ store_executor_outputs=store_executor_outputs,
217
+ run_context=run_context,
218
+ session_state=session_state,
219
+ workflow_session=workflow_session,
220
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
221
+ num_history_runs=num_history_runs,
222
+ )
223
+
224
+ # Handle both single StepOutput and List[StepOutput]
225
+ if isinstance(step_output, list):
226
+ all_results.extend(step_output)
227
+ if step_output:
228
+ step_name = getattr(step, "name", f"step_{i}")
229
+ router_step_outputs[step_name] = step_output[-1]
230
+
231
+ if any(output.stop for output in step_output):
232
+ logger.info(f"Early termination requested by step {step_name}")
233
+ break
234
+ else:
235
+ all_results.append(step_output)
236
+ step_name = getattr(step, "name", f"step_{i}")
237
+ router_step_outputs[step_name] = step_output
238
+
239
+ if step_output.stop:
240
+ logger.info(f"Early termination requested by step {step_name}")
241
+ break
242
+
243
+ current_step_input = self._update_step_input_from_outputs(
244
+ current_step_input, step_output, router_step_outputs
245
+ )
246
+
247
+ except Exception as e:
248
+ step_name = getattr(step, "name", f"step_{i}")
249
+ logger.error(f"Router step {step_name} failed: {e}")
250
+ error_output = StepOutput(
251
+ step_name=step_name,
252
+ content=f"Step {step_name} failed: {str(e)}",
253
+ success=False,
254
+ error=str(e),
255
+ )
256
+ all_results.append(error_output)
257
+ break
258
+
259
+ log_debug(f"Router End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
260
+
261
+ return StepOutput(
262
+ step_name=self.name,
263
+ step_id=router_step_id,
264
+ step_type=StepType.ROUTER,
265
+ content=f"Router {self.name} completed with {len(all_results)} results",
266
+ success=all(result.success for result in all_results) if all_results else True,
267
+ steps=all_results,
268
+ )
269
+
270
+ def execute_stream(
271
+ self,
272
+ step_input: StepInput,
273
+ session_id: Optional[str] = None,
274
+ user_id: Optional[str] = None,
275
+ run_context: Optional[RunContext] = None,
276
+ session_state: Optional[Dict[str, Any]] = None,
277
+ stream_events: bool = False,
278
+ stream_intermediate_steps: bool = False,
279
+ stream_executor_events: bool = True,
280
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
281
+ step_index: Optional[Union[int, tuple]] = None,
282
+ store_executor_outputs: bool = True,
283
+ parent_step_id: Optional[str] = None,
284
+ workflow_session: Optional[WorkflowSession] = None,
285
+ add_workflow_history_to_steps: Optional[bool] = False,
286
+ num_history_runs: int = 3,
287
+ ) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
288
+ """Execute the router with streaming support"""
289
+ log_debug(f"Router Start: {self.name}", center=True, symbol="-")
290
+
291
+ self._prepare_steps()
292
+
293
+ router_step_id = str(uuid4())
294
+
295
+ # Route to appropriate steps
296
+ if run_context is not None and run_context.session_state is not None:
297
+ steps_to_execute = self._route_steps(step_input, session_state=run_context.session_state)
298
+ else:
299
+ steps_to_execute = self._route_steps(step_input, session_state=session_state)
300
+ log_debug(f"Router {self.name}: Selected {len(steps_to_execute)} steps to execute")
301
+
302
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
303
+ stream_events = stream_events or stream_intermediate_steps
304
+
305
+ if stream_events and workflow_run_response:
306
+ # Yield router started event
307
+ yield RouterExecutionStartedEvent(
308
+ run_id=workflow_run_response.run_id or "",
309
+ workflow_name=workflow_run_response.workflow_name or "",
310
+ workflow_id=workflow_run_response.workflow_id or "",
311
+ session_id=workflow_run_response.session_id or "",
312
+ step_name=self.name,
313
+ step_index=step_index,
314
+ selected_steps=[getattr(step, "name", f"step_{i}") for i, step in enumerate(steps_to_execute)],
315
+ step_id=router_step_id,
316
+ parent_step_id=parent_step_id,
317
+ )
318
+
319
+ if not steps_to_execute:
320
+ # Yield router completed event for empty case
321
+ if stream_events and workflow_run_response:
322
+ yield RouterExecutionCompletedEvent(
323
+ run_id=workflow_run_response.run_id or "",
324
+ workflow_name=workflow_run_response.workflow_name or "",
325
+ workflow_id=workflow_run_response.workflow_id or "",
326
+ session_id=workflow_run_response.session_id or "",
327
+ step_name=self.name,
328
+ step_index=step_index,
329
+ selected_steps=[],
330
+ executed_steps=0,
331
+ step_results=[],
332
+ step_id=router_step_id,
333
+ parent_step_id=parent_step_id,
334
+ )
335
+ return
336
+
337
+ all_results = []
338
+ current_step_input = step_input
339
+ router_step_outputs = {}
340
+
341
+ for i, step in enumerate(steps_to_execute):
342
+ try:
343
+ step_outputs_for_step = []
344
+ # Stream step execution
345
+ for event in step.execute_stream(
346
+ current_step_input,
347
+ session_id=session_id,
348
+ user_id=user_id,
349
+ stream_events=stream_events,
350
+ stream_executor_events=stream_executor_events,
351
+ workflow_run_response=workflow_run_response,
352
+ step_index=step_index,
353
+ store_executor_outputs=store_executor_outputs,
354
+ run_context=run_context,
355
+ session_state=session_state,
356
+ parent_step_id=router_step_id,
357
+ workflow_session=workflow_session,
358
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
359
+ num_history_runs=num_history_runs,
360
+ ):
361
+ if isinstance(event, StepOutput):
362
+ step_outputs_for_step.append(event)
363
+ all_results.append(event)
364
+ else:
365
+ # Yield other events (streaming content, step events, etc.)
366
+ yield event
367
+
368
+ step_name = getattr(step, "name", f"step_{i}")
369
+ log_debug(f"Router step {step_name} streaming completed")
370
+
371
+ if step_outputs_for_step:
372
+ if len(step_outputs_for_step) == 1:
373
+ router_step_outputs[step_name] = step_outputs_for_step[0]
374
+
375
+ if step_outputs_for_step[0].stop:
376
+ logger.info(f"Early termination requested by step {step_name}")
377
+ break
378
+
379
+ current_step_input = self._update_step_input_from_outputs(
380
+ current_step_input, step_outputs_for_step[0], router_step_outputs
381
+ )
382
+ else:
383
+ # Use last output
384
+ router_step_outputs[step_name] = step_outputs_for_step[-1]
385
+
386
+ if any(output.stop for output in step_outputs_for_step):
387
+ logger.info(f"Early termination requested by step {step_name}")
388
+ break
389
+
390
+ current_step_input = self._update_step_input_from_outputs(
391
+ current_step_input, step_outputs_for_step, router_step_outputs
392
+ )
393
+
394
+ except Exception as e:
395
+ step_name = getattr(step, "name", f"step_{i}")
396
+ logger.error(f"Router step {step_name} streaming failed: {e}")
397
+ error_output = StepOutput(
398
+ step_name=step_name,
399
+ content=f"Step {step_name} failed: {str(e)}",
400
+ success=False,
401
+ error=str(e),
402
+ )
403
+ all_results.append(error_output)
404
+ break
405
+
406
+ log_debug(f"Router End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
407
+
408
+ if stream_events and workflow_run_response:
409
+ # Yield router completed event
410
+ yield RouterExecutionCompletedEvent(
411
+ run_id=workflow_run_response.run_id or "",
412
+ workflow_name=workflow_run_response.workflow_name or "",
413
+ workflow_id=workflow_run_response.workflow_id or "",
414
+ session_id=workflow_run_response.session_id or "",
415
+ step_name=self.name,
416
+ step_index=step_index,
417
+ selected_steps=[getattr(step, "name", f"step_{i}") for i, step in enumerate(steps_to_execute)],
418
+ executed_steps=len(steps_to_execute),
419
+ step_results=all_results,
420
+ step_id=router_step_id,
421
+ parent_step_id=parent_step_id,
422
+ )
423
+
424
+ yield StepOutput(
425
+ step_name=self.name,
426
+ step_id=router_step_id,
427
+ step_type=StepType.ROUTER,
428
+ content=f"Router {self.name} completed with {len(all_results)} results",
429
+ success=all(result.success for result in all_results) if all_results else True,
430
+ steps=all_results,
431
+ )
432
+
433
+ async def aexecute(
434
+ self,
435
+ step_input: StepInput,
436
+ session_id: Optional[str] = None,
437
+ user_id: Optional[str] = None,
438
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
439
+ run_context: Optional[RunContext] = None,
440
+ session_state: Optional[Dict[str, Any]] = None,
441
+ store_executor_outputs: bool = True,
442
+ workflow_session: Optional[WorkflowSession] = None,
443
+ add_workflow_history_to_steps: Optional[bool] = False,
444
+ num_history_runs: int = 3,
445
+ ) -> StepOutput:
446
+ """Async execute the router and its selected steps with sequential chaining"""
447
+ log_debug(f"Router Start: {self.name}", center=True, symbol="-")
448
+
449
+ router_step_id = str(uuid4())
450
+
451
+ self._prepare_steps()
452
+
453
+ # Route to appropriate steps
454
+ if run_context is not None and run_context.session_state is not None:
455
+ steps_to_execute = await self._aroute_steps(step_input, session_state=run_context.session_state)
456
+ else:
457
+ steps_to_execute = await self._aroute_steps(step_input, session_state=session_state)
458
+ log_debug(f"Router {self.name} selected: {len(steps_to_execute)} steps to execute")
459
+
460
+ if not steps_to_execute:
461
+ return StepOutput(
462
+ step_name=self.name,
463
+ step_id=router_step_id,
464
+ step_type=StepType.ROUTER,
465
+ content=f"Router {self.name} completed with 0 results (no steps selected)",
466
+ success=True,
467
+ )
468
+
469
+ # Chain steps sequentially like Loop does
470
+ all_results: List[StepOutput] = []
471
+ current_step_input = step_input
472
+ router_step_outputs = {}
473
+
474
+ for i, step in enumerate(steps_to_execute):
475
+ try:
476
+ step_output = await step.aexecute(
477
+ current_step_input,
478
+ session_id=session_id,
479
+ user_id=user_id,
480
+ workflow_run_response=workflow_run_response,
481
+ store_executor_outputs=store_executor_outputs,
482
+ run_context=run_context,
483
+ session_state=session_state,
484
+ workflow_session=workflow_session,
485
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
486
+ num_history_runs=num_history_runs,
487
+ )
488
+ # Handle both single StepOutput and List[StepOutput]
489
+ if isinstance(step_output, list):
490
+ all_results.extend(step_output)
491
+ if step_output:
492
+ step_name = getattr(step, "name", f"step_{i}")
493
+ router_step_outputs[step_name] = step_output[-1]
494
+
495
+ if any(output.stop for output in step_output):
496
+ logger.info(f"Early termination requested by step {step_name}")
497
+ break
498
+ else:
499
+ all_results.append(step_output)
500
+ step_name = getattr(step, "name", f"step_{i}")
501
+ router_step_outputs[step_name] = step_output
502
+
503
+ if step_output.stop:
504
+ logger.info(f"Early termination requested by step {step_name}")
505
+ break
506
+
507
+ step_name = getattr(step, "name", f"step_{i}")
508
+ log_debug(f"Router step {step_name} async completed")
509
+
510
+ current_step_input = self._update_step_input_from_outputs(
511
+ current_step_input, step_output, router_step_outputs
512
+ )
513
+
514
+ except Exception as e:
515
+ step_name = getattr(step, "name", f"step_{i}")
516
+ logger.error(f"Router step {step_name} async failed: {e}")
517
+ error_output = StepOutput(
518
+ step_name=step_name,
519
+ content=f"Step {step_name} failed: {str(e)}",
520
+ success=False,
521
+ error=str(e),
522
+ )
523
+ all_results.append(error_output)
524
+ break # Stop on first error
525
+
526
+ log_debug(f"Router End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
527
+
528
+ return StepOutput(
529
+ step_name=self.name,
530
+ step_id=router_step_id,
531
+ step_type=StepType.ROUTER,
532
+ content=f"Router {self.name} completed with {len(all_results)} results",
533
+ success=all(result.success for result in all_results) if all_results else True,
534
+ steps=all_results,
535
+ )
536
+
537
+ async def aexecute_stream(
538
+ self,
539
+ step_input: StepInput,
540
+ session_id: Optional[str] = None,
541
+ user_id: Optional[str] = None,
542
+ run_context: Optional[RunContext] = None,
543
+ session_state: Optional[Dict[str, Any]] = None,
544
+ stream_events: bool = False,
545
+ stream_intermediate_steps: bool = False,
546
+ stream_executor_events: bool = True,
547
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
548
+ step_index: Optional[Union[int, tuple]] = None,
549
+ store_executor_outputs: bool = True,
550
+ parent_step_id: Optional[str] = None,
551
+ workflow_session: Optional[WorkflowSession] = None,
552
+ add_workflow_history_to_steps: Optional[bool] = False,
553
+ num_history_runs: int = 3,
554
+ ) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
555
+ """Async execute the router with streaming support"""
556
+ log_debug(f"Router Start: {self.name}", center=True, symbol="-")
557
+
558
+ self._prepare_steps()
559
+
560
+ router_step_id = str(uuid4())
561
+
562
+ # Route to appropriate steps
563
+ if run_context is not None and run_context.session_state is not None:
564
+ steps_to_execute = await self._aroute_steps(step_input, session_state=run_context.session_state)
565
+ else:
566
+ steps_to_execute = await self._aroute_steps(step_input, session_state=session_state)
567
+ log_debug(f"Router {self.name} selected: {len(steps_to_execute)} steps to execute")
568
+
569
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
570
+ stream_events = stream_events or stream_intermediate_steps
571
+
572
+ if stream_events and workflow_run_response:
573
+ # Yield router started event
574
+ yield RouterExecutionStartedEvent(
575
+ run_id=workflow_run_response.run_id or "",
576
+ workflow_name=workflow_run_response.workflow_name or "",
577
+ workflow_id=workflow_run_response.workflow_id or "",
578
+ session_id=workflow_run_response.session_id or "",
579
+ step_name=self.name,
580
+ step_index=step_index,
581
+ selected_steps=[getattr(step, "name", f"step_{i}") for i, step in enumerate(steps_to_execute)],
582
+ step_id=router_step_id,
583
+ parent_step_id=parent_step_id,
584
+ )
585
+
586
+ if not steps_to_execute:
587
+ if stream_events and workflow_run_response:
588
+ # Yield router completed event for empty case
589
+ yield RouterExecutionCompletedEvent(
590
+ run_id=workflow_run_response.run_id or "",
591
+ workflow_name=workflow_run_response.workflow_name or "",
592
+ workflow_id=workflow_run_response.workflow_id or "",
593
+ session_id=workflow_run_response.session_id or "",
594
+ step_name=self.name,
595
+ step_index=step_index,
596
+ selected_steps=[],
597
+ executed_steps=0,
598
+ step_results=[],
599
+ step_id=router_step_id,
600
+ parent_step_id=parent_step_id,
601
+ )
602
+ return
603
+
604
+ # Chain steps sequentially like Loop does
605
+ all_results = []
606
+ current_step_input = step_input
607
+ router_step_outputs = {}
608
+
609
+ for i, step in enumerate(steps_to_execute):
610
+ try:
611
+ step_outputs_for_step = []
612
+
613
+ # Stream step execution - mirroring Loop logic
614
+ async for event in step.aexecute_stream(
615
+ current_step_input,
616
+ session_id=session_id,
617
+ user_id=user_id,
618
+ stream_events=stream_events,
619
+ stream_executor_events=stream_executor_events,
620
+ workflow_run_response=workflow_run_response,
621
+ step_index=step_index,
622
+ store_executor_outputs=store_executor_outputs,
623
+ run_context=run_context,
624
+ session_state=session_state,
625
+ parent_step_id=router_step_id,
626
+ workflow_session=workflow_session,
627
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
628
+ num_history_runs=num_history_runs,
629
+ ):
630
+ if isinstance(event, StepOutput):
631
+ step_outputs_for_step.append(event)
632
+ all_results.append(event)
633
+ else:
634
+ # Yield other events (streaming content, step events, etc.)
635
+ yield event
636
+
637
+ step_name = getattr(step, "name", f"step_{i}")
638
+ log_debug(f"Router step {step_name} async streaming completed")
639
+
640
+ if step_outputs_for_step:
641
+ if len(step_outputs_for_step) == 1:
642
+ router_step_outputs[step_name] = step_outputs_for_step[0]
643
+
644
+ if step_outputs_for_step[0].stop:
645
+ logger.info(f"Early termination requested by step {step_name}")
646
+ break
647
+
648
+ current_step_input = self._update_step_input_from_outputs(
649
+ current_step_input, step_outputs_for_step[0], router_step_outputs
650
+ )
651
+ else:
652
+ # Use last output
653
+ router_step_outputs[step_name] = step_outputs_for_step[-1]
654
+
655
+ if any(output.stop for output in step_outputs_for_step):
656
+ logger.info(f"Early termination requested by step {step_name}")
657
+ break
658
+
659
+ current_step_input = self._update_step_input_from_outputs(
660
+ current_step_input, step_outputs_for_step, router_step_outputs
661
+ )
662
+
663
+ except Exception as e:
664
+ step_name = getattr(step, "name", f"step_{i}")
665
+ logger.error(f"Router step {step_name} async streaming failed: {e}")
666
+ error_output = StepOutput(
667
+ step_name=step_name,
668
+ content=f"Step {step_name} failed: {str(e)}",
669
+ success=False,
670
+ error=str(e),
671
+ )
672
+ all_results.append(error_output)
673
+ break # Stop on first error
674
+
675
+ log_debug(f"Router End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
676
+
677
+ if stream_events and workflow_run_response:
678
+ # Yield router completed event
679
+ yield RouterExecutionCompletedEvent(
680
+ run_id=workflow_run_response.run_id or "",
681
+ workflow_name=workflow_run_response.workflow_name or "",
682
+ workflow_id=workflow_run_response.workflow_id or "",
683
+ session_id=workflow_run_response.session_id or "",
684
+ step_name=self.name,
685
+ step_index=step_index,
686
+ selected_steps=[getattr(step, "name", f"step_{i}") for i, step in enumerate(steps_to_execute)],
687
+ executed_steps=len(steps_to_execute),
688
+ step_results=all_results,
689
+ step_id=router_step_id,
690
+ parent_step_id=parent_step_id,
691
+ )
692
+
693
+ yield StepOutput(
694
+ step_name=self.name,
695
+ step_id=router_step_id,
696
+ step_type=StepType.ROUTER,
697
+ content=f"Router {self.name} completed with {len(all_results)} results",
698
+ success=all(result.success for result in all_results) if all_results else True,
699
+ error=None,
700
+ stop=False,
701
+ steps=all_results,
702
+ )