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