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,738 @@
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
+ ConditionExecutionCompletedEvent,
11
+ ConditionExecutionStartedEvent,
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 Condition:
37
+ """A condition that executes a step (or list of steps) if the condition is met"""
38
+
39
+ # Evaluator should only return boolean
40
+ evaluator: Union[
41
+ Callable[[StepInput], bool],
42
+ Callable[[StepInput], Awaitable[bool]],
43
+ bool,
44
+ ]
45
+ steps: WorkflowSteps
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.loop import Loop
55
+ from agno.workflow.parallel import Parallel
56
+ from agno.workflow.router import Router
57
+ from agno.workflow.step import Step
58
+ from agno.workflow.steps import Steps
59
+
60
+ prepared_steps: WorkflowSteps = []
61
+ for step in self.steps:
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
+ condition_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
+ # Use the last output's content for chaining
91
+ previous_step_content = step_outputs[-1].content if step_outputs else None
92
+ else:
93
+ # Single output
94
+ all_images = step_outputs.images or []
95
+ all_videos = step_outputs.videos or []
96
+ all_audio = step_outputs.audio or []
97
+ previous_step_content = step_outputs.content
98
+
99
+ updated_previous_step_outputs = {}
100
+ if step_input.previous_step_outputs:
101
+ updated_previous_step_outputs.update(step_input.previous_step_outputs)
102
+ if condition_step_outputs:
103
+ updated_previous_step_outputs.update(condition_step_outputs)
104
+
105
+ return StepInput(
106
+ input=step_input.input,
107
+ previous_step_content=previous_step_content,
108
+ previous_step_outputs=updated_previous_step_outputs,
109
+ additional_data=step_input.additional_data,
110
+ images=current_images + all_images,
111
+ videos=current_videos + all_videos,
112
+ audio=current_audio + all_audio,
113
+ )
114
+
115
+ def _evaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
116
+ """Evaluate the condition and return boolean result"""
117
+ if isinstance(self.evaluator, bool):
118
+ return self.evaluator
119
+
120
+ if callable(self.evaluator):
121
+ if session_state is not None and self._evaluator_has_session_state_param():
122
+ result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
123
+ else:
124
+ result = self.evaluator(step_input)
125
+
126
+ if isinstance(result, bool):
127
+ return result
128
+ else:
129
+ logger.warning(f"Condition evaluator returned unexpected type: {type(result)}, expected bool")
130
+ return False
131
+
132
+ return False
133
+
134
+ async def _aevaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
135
+ """Async version of condition evaluation"""
136
+ if isinstance(self.evaluator, bool):
137
+ return self.evaluator
138
+
139
+ if callable(self.evaluator):
140
+ has_session_state = session_state is not None and self._evaluator_has_session_state_param()
141
+
142
+ if inspect.iscoroutinefunction(self.evaluator):
143
+ if has_session_state:
144
+ result = await self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
145
+ else:
146
+ result = await self.evaluator(step_input)
147
+ else:
148
+ if has_session_state:
149
+ result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
150
+ else:
151
+ result = self.evaluator(step_input)
152
+
153
+ if isinstance(result, bool):
154
+ return result
155
+ else:
156
+ logger.warning(f"Condition evaluator returned unexpected type: {type(result)}, expected bool")
157
+ return False
158
+
159
+ return False
160
+
161
+ def _evaluator_has_session_state_param(self) -> bool:
162
+ """Check if the evaluator function has a session_state parameter"""
163
+ if not callable(self.evaluator):
164
+ return False
165
+
166
+ try:
167
+ sig = inspect.signature(self.evaluator)
168
+ return "session_state" in sig.parameters
169
+ except Exception:
170
+ return False
171
+
172
+ def execute(
173
+ self,
174
+ step_input: StepInput,
175
+ session_id: Optional[str] = None,
176
+ user_id: Optional[str] = None,
177
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
178
+ store_executor_outputs: bool = True,
179
+ run_context: Optional[RunContext] = None,
180
+ session_state: Optional[Dict[str, Any]] = None,
181
+ workflow_session: Optional[WorkflowSession] = None,
182
+ add_workflow_history_to_steps: Optional[bool] = False,
183
+ num_history_runs: int = 3,
184
+ ) -> StepOutput:
185
+ """Execute the condition and its steps with sequential chaining if condition is true"""
186
+ log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
187
+
188
+ conditional_step_id = str(uuid4())
189
+
190
+ self._prepare_steps()
191
+
192
+ # Evaluate the condition
193
+ if run_context is not None and run_context.session_state is not None:
194
+ condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
195
+ else:
196
+ condition_result = self._evaluate_condition(step_input, session_state=session_state)
197
+
198
+ log_debug(f"Condition {self.name} evaluated to: {condition_result}")
199
+
200
+ if not condition_result:
201
+ log_debug(f"Condition {self.name} not met, skipping {len(self.steps)} steps")
202
+ return StepOutput(
203
+ step_name=self.name,
204
+ step_id=conditional_step_id,
205
+ step_type=StepType.CONDITION,
206
+ content=f"Condition {self.name} not met - skipped {len(self.steps)} steps",
207
+ success=True,
208
+ )
209
+
210
+ log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
211
+ all_results: List[StepOutput] = []
212
+ current_step_input = step_input
213
+ condition_step_outputs = {}
214
+
215
+ for i, step in enumerate(self.steps):
216
+ try:
217
+ step_output = step.execute( # type: ignore[union-attr]
218
+ current_step_input,
219
+ session_id=session_id,
220
+ user_id=user_id,
221
+ workflow_run_response=workflow_run_response,
222
+ store_executor_outputs=store_executor_outputs,
223
+ run_context=run_context,
224
+ session_state=session_state,
225
+ workflow_session=workflow_session,
226
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
227
+ num_history_runs=num_history_runs,
228
+ )
229
+
230
+ # Handle both single StepOutput and List[StepOutput] (from Loop/Condition/Router steps)
231
+ if isinstance(step_output, list):
232
+ all_results.extend(step_output)
233
+ if step_output:
234
+ step_name = getattr(step, "name", f"step_{i}")
235
+ log_debug(f"Executing condition step {i + 1}/{len(self.steps)}: {step_name}")
236
+
237
+ condition_step_outputs[step_name] = step_output[-1]
238
+
239
+ if any(output.stop for output in step_output):
240
+ logger.info(f"Early termination requested by condition step {step_name}")
241
+ break
242
+ else:
243
+ all_results.append(step_output)
244
+ step_name = getattr(step, "name", f"step_{i}")
245
+ condition_step_outputs[step_name] = step_output
246
+
247
+ if step_output.stop:
248
+ logger.info(f"Early termination requested by condition step {step_name}")
249
+ break
250
+
251
+ step_name = getattr(step, "name", f"step_{i}")
252
+ log_debug(f"Condition step {step_name} completed")
253
+
254
+ current_step_input = self._update_step_input_from_outputs(
255
+ current_step_input, step_output, condition_step_outputs
256
+ )
257
+
258
+ except Exception as e:
259
+ step_name = getattr(step, "name", f"step_{i}")
260
+ logger.error(f"Condition step {step_name} failed: {e}")
261
+ error_output = StepOutput(
262
+ step_name=step_name,
263
+ content=f"Step {step_name} failed: {str(e)}",
264
+ success=False,
265
+ error=str(e),
266
+ )
267
+ all_results.append(error_output)
268
+ break
269
+
270
+ log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
271
+
272
+ return StepOutput(
273
+ step_name=self.name,
274
+ step_id=conditional_step_id,
275
+ step_type=StepType.CONDITION,
276
+ content=f"Condition {self.name} completed with {len(all_results)} results",
277
+ success=all(result.success for result in all_results) if all_results else True,
278
+ error=None,
279
+ stop=False,
280
+ steps=all_results,
281
+ )
282
+
283
+ def execute_stream(
284
+ self,
285
+ step_input: StepInput,
286
+ session_id: Optional[str] = None,
287
+ user_id: Optional[str] = None,
288
+ stream_events: bool = False,
289
+ stream_intermediate_steps: bool = False, # type: ignore
290
+ stream_executor_events: bool = True,
291
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
292
+ step_index: Optional[Union[int, tuple]] = None,
293
+ store_executor_outputs: bool = True,
294
+ run_context: Optional[RunContext] = None,
295
+ session_state: Optional[Dict[str, Any]] = None,
296
+ parent_step_id: Optional[str] = None,
297
+ workflow_session: Optional[WorkflowSession] = None,
298
+ add_workflow_history_to_steps: Optional[bool] = False,
299
+ num_history_runs: int = 3,
300
+ ) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
301
+ """Execute the condition with streaming support - mirrors Loop logic"""
302
+ log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
303
+
304
+ conditional_step_id = str(uuid4())
305
+
306
+ self._prepare_steps()
307
+
308
+ # Evaluate the condition
309
+ if run_context is not None and run_context.session_state is not None:
310
+ condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
311
+ else:
312
+ condition_result = self._evaluate_condition(step_input, session_state=session_state)
313
+ log_debug(f"Condition {self.name} evaluated to: {condition_result}")
314
+
315
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
316
+ stream_events = stream_events or stream_intermediate_steps
317
+
318
+ if stream_events and workflow_run_response:
319
+ # Yield condition started event
320
+ yield ConditionExecutionStartedEvent(
321
+ run_id=workflow_run_response.run_id or "",
322
+ workflow_name=workflow_run_response.workflow_name or "",
323
+ workflow_id=workflow_run_response.workflow_id or "",
324
+ session_id=workflow_run_response.session_id or "",
325
+ step_name=self.name,
326
+ step_index=step_index,
327
+ condition_result=condition_result,
328
+ step_id=conditional_step_id,
329
+ parent_step_id=parent_step_id,
330
+ )
331
+
332
+ if not condition_result:
333
+ if stream_events and workflow_run_response:
334
+ # Yield condition completed event for empty case
335
+ yield ConditionExecutionCompletedEvent(
336
+ run_id=workflow_run_response.run_id or "",
337
+ workflow_name=workflow_run_response.workflow_name or "",
338
+ workflow_id=workflow_run_response.workflow_id or "",
339
+ session_id=workflow_run_response.session_id or "",
340
+ step_name=self.name,
341
+ step_index=step_index,
342
+ condition_result=False,
343
+ executed_steps=0,
344
+ step_results=[],
345
+ step_id=conditional_step_id,
346
+ parent_step_id=parent_step_id,
347
+ )
348
+ return
349
+
350
+ log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
351
+ all_results = []
352
+ current_step_input = step_input
353
+ condition_step_outputs = {}
354
+
355
+ for i, step in enumerate(self.steps):
356
+ try:
357
+ step_outputs_for_step = []
358
+
359
+ # Create child index for each step within condition
360
+ if step_index is None or isinstance(step_index, int):
361
+ # Condition is a main step - child steps get x.1, x.2, x.3 format
362
+ child_step_index = (step_index if step_index is not None else 1, i)
363
+ else:
364
+ # Condition is already a child step - child steps get same parent number: x.y, x.y, x.y
365
+ child_step_index = step_index
366
+
367
+ # Stream step execution
368
+ for event in step.execute_stream( # type: ignore[union-attr]
369
+ current_step_input,
370
+ session_id=session_id,
371
+ user_id=user_id,
372
+ stream_events=stream_events,
373
+ stream_executor_events=stream_executor_events,
374
+ workflow_run_response=workflow_run_response,
375
+ step_index=child_step_index,
376
+ store_executor_outputs=store_executor_outputs,
377
+ run_context=run_context,
378
+ session_state=session_state,
379
+ parent_step_id=conditional_step_id,
380
+ workflow_session=workflow_session,
381
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
382
+ num_history_runs=num_history_runs,
383
+ ):
384
+ if isinstance(event, StepOutput):
385
+ step_outputs_for_step.append(event)
386
+ all_results.append(event)
387
+ else:
388
+ # Yield other events (streaming content, step events, etc.)
389
+ yield event
390
+
391
+ step_name = getattr(step, "name", f"step_{i}")
392
+ log_debug(f"Condition step {step_name} streaming completed")
393
+
394
+ if step_outputs_for_step:
395
+ if len(step_outputs_for_step) == 1:
396
+ condition_step_outputs[step_name] = step_outputs_for_step[0]
397
+
398
+ if step_outputs_for_step[0].stop:
399
+ logger.info(f"Early termination requested by condition step {step_name}")
400
+ break
401
+
402
+ current_step_input = self._update_step_input_from_outputs(
403
+ current_step_input, step_outputs_for_step[0], condition_step_outputs
404
+ )
405
+ else:
406
+ # Use last output
407
+ condition_step_outputs[step_name] = step_outputs_for_step[-1]
408
+
409
+ if any(output.stop for output in step_outputs_for_step):
410
+ logger.info(f"Early termination requested by condition step {step_name}")
411
+ break
412
+
413
+ current_step_input = self._update_step_input_from_outputs(
414
+ current_step_input, step_outputs_for_step, condition_step_outputs
415
+ )
416
+
417
+ except Exception as e:
418
+ step_name = getattr(step, "name", f"step_{i}")
419
+ logger.error(f"Condition step {step_name} streaming failed: {e}")
420
+ error_output = StepOutput(
421
+ step_name=step_name,
422
+ content=f"Step {step_name} failed: {str(e)}",
423
+ success=False,
424
+ error=str(e),
425
+ )
426
+ all_results.append(error_output)
427
+ break
428
+
429
+ log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
430
+ if stream_events and workflow_run_response:
431
+ # Yield condition completed event
432
+ yield ConditionExecutionCompletedEvent(
433
+ run_id=workflow_run_response.run_id or "",
434
+ workflow_name=workflow_run_response.workflow_name or "",
435
+ workflow_id=workflow_run_response.workflow_id or "",
436
+ session_id=workflow_run_response.session_id or "",
437
+ step_name=self.name,
438
+ step_index=step_index,
439
+ condition_result=True,
440
+ executed_steps=len(self.steps),
441
+ step_results=all_results,
442
+ step_id=conditional_step_id,
443
+ parent_step_id=parent_step_id,
444
+ )
445
+
446
+ yield StepOutput(
447
+ step_name=self.name,
448
+ step_id=conditional_step_id,
449
+ step_type=StepType.CONDITION,
450
+ content=f"Condition {self.name} completed with {len(all_results)} results",
451
+ success=all(result.success for result in all_results) if all_results else True,
452
+ steps=all_results,
453
+ )
454
+
455
+ async def aexecute(
456
+ self,
457
+ step_input: StepInput,
458
+ session_id: Optional[str] = None,
459
+ user_id: Optional[str] = None,
460
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
461
+ store_executor_outputs: bool = True,
462
+ run_context: Optional[RunContext] = None,
463
+ session_state: Optional[Dict[str, Any]] = None,
464
+ workflow_session: Optional[WorkflowSession] = None,
465
+ add_workflow_history_to_steps: Optional[bool] = False,
466
+ num_history_runs: int = 3,
467
+ ) -> StepOutput:
468
+ """Async execute the condition and its steps with sequential chaining"""
469
+ log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
470
+
471
+ conditional_step_id = str(uuid4())
472
+
473
+ self._prepare_steps()
474
+
475
+ # Evaluate the condition
476
+ if run_context is not None and run_context.session_state is not None:
477
+ condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
478
+ else:
479
+ condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
480
+ log_debug(f"Condition {self.name} evaluated to: {condition_result}")
481
+
482
+ if not condition_result:
483
+ log_debug(f"Condition {self.name} not met, skipping {len(self.steps)} steps")
484
+ return StepOutput(
485
+ step_name=self.name,
486
+ step_id=str(uuid4()),
487
+ step_type=StepType.CONDITION,
488
+ content=f"Condition {self.name} not met - skipped {len(self.steps)} steps",
489
+ success=True,
490
+ )
491
+
492
+ log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
493
+
494
+ # Chain steps sequentially like Loop does
495
+ all_results: List[StepOutput] = []
496
+ current_step_input = step_input
497
+ condition_step_outputs = {}
498
+
499
+ for i, step in enumerate(self.steps):
500
+ try:
501
+ step_output = await step.aexecute( # type: ignore[union-attr]
502
+ current_step_input,
503
+ session_id=session_id,
504
+ user_id=user_id,
505
+ workflow_run_response=workflow_run_response,
506
+ store_executor_outputs=store_executor_outputs,
507
+ run_context=run_context,
508
+ session_state=session_state,
509
+ workflow_session=workflow_session,
510
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
511
+ num_history_runs=num_history_runs,
512
+ )
513
+
514
+ # Handle both single StepOutput and List[StepOutput]
515
+ if isinstance(step_output, list):
516
+ all_results.extend(step_output)
517
+ if step_output:
518
+ step_name = getattr(step, "name", f"step_{i}")
519
+ condition_step_outputs[step_name] = step_output[-1]
520
+
521
+ if any(output.stop for output in step_output):
522
+ logger.info(f"Early termination requested by condition step {step_name}")
523
+ break
524
+ else:
525
+ all_results.append(step_output)
526
+ step_name = getattr(step, "name", f"step_{i}")
527
+ condition_step_outputs[step_name] = step_output
528
+
529
+ if step_output.stop:
530
+ logger.info(f"Early termination requested by condition step {step_name}")
531
+ break
532
+
533
+ step_name = getattr(step, "name", f"step_{i}")
534
+ log_debug(f"Condition step {step_name} async completed")
535
+
536
+ current_step_input = self._update_step_input_from_outputs(
537
+ current_step_input, step_output, condition_step_outputs
538
+ )
539
+
540
+ except Exception as e:
541
+ step_name = getattr(step, "name", f"step_{i}")
542
+ logger.error(f"Condition step {step_name} async failed: {e}")
543
+ error_output = StepOutput(
544
+ step_name=step_name,
545
+ content=f"Step {step_name} failed: {str(e)}",
546
+ success=False,
547
+ error=str(e),
548
+ )
549
+ all_results.append(error_output)
550
+ break
551
+
552
+ log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
553
+
554
+ return StepOutput(
555
+ step_name=self.name,
556
+ step_id=conditional_step_id,
557
+ step_type=StepType.CONDITION,
558
+ content=f"Condition {self.name} completed with {len(all_results)} results",
559
+ success=all(result.success for result in all_results) if all_results else True,
560
+ error=None,
561
+ stop=False,
562
+ steps=all_results,
563
+ )
564
+
565
+ async def aexecute_stream(
566
+ self,
567
+ step_input: StepInput,
568
+ session_id: Optional[str] = None,
569
+ user_id: Optional[str] = None,
570
+ stream_events: bool = False,
571
+ stream_intermediate_steps: bool = False,
572
+ stream_executor_events: bool = True,
573
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
574
+ step_index: Optional[Union[int, tuple]] = None,
575
+ store_executor_outputs: bool = True,
576
+ run_context: Optional[RunContext] = None,
577
+ session_state: Optional[Dict[str, Any]] = None,
578
+ parent_step_id: Optional[str] = None,
579
+ workflow_session: Optional[WorkflowSession] = None,
580
+ add_workflow_history_to_steps: Optional[bool] = False,
581
+ num_history_runs: int = 3,
582
+ ) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
583
+ """Async execute the condition with streaming support - mirrors Loop logic"""
584
+ log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
585
+
586
+ conditional_step_id = str(uuid4())
587
+
588
+ self._prepare_steps()
589
+
590
+ # Evaluate the condition
591
+ if run_context is not None and run_context.session_state is not None:
592
+ condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
593
+ else:
594
+ condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
595
+ log_debug(f"Condition {self.name} evaluated to: {condition_result}")
596
+
597
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
598
+ stream_events = stream_events or stream_intermediate_steps
599
+
600
+ if stream_events and workflow_run_response:
601
+ # Yield condition started event
602
+ yield ConditionExecutionStartedEvent(
603
+ run_id=workflow_run_response.run_id or "",
604
+ workflow_name=workflow_run_response.workflow_name or "",
605
+ workflow_id=workflow_run_response.workflow_id or "",
606
+ session_id=workflow_run_response.session_id or "",
607
+ step_name=self.name,
608
+ step_index=step_index,
609
+ condition_result=condition_result,
610
+ step_id=conditional_step_id,
611
+ parent_step_id=parent_step_id,
612
+ )
613
+
614
+ if not condition_result:
615
+ if stream_events and workflow_run_response:
616
+ # Yield condition completed event for empty case
617
+ yield ConditionExecutionCompletedEvent(
618
+ run_id=workflow_run_response.run_id or "",
619
+ workflow_name=workflow_run_response.workflow_name or "",
620
+ workflow_id=workflow_run_response.workflow_id or "",
621
+ session_id=workflow_run_response.session_id or "",
622
+ step_name=self.name,
623
+ step_index=step_index,
624
+ condition_result=False,
625
+ executed_steps=0,
626
+ step_results=[],
627
+ step_id=conditional_step_id,
628
+ parent_step_id=parent_step_id,
629
+ )
630
+ return
631
+
632
+ log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
633
+
634
+ # Chain steps sequentially like Loop does
635
+ all_results = []
636
+ current_step_input = step_input
637
+ condition_step_outputs = {}
638
+
639
+ for i, step in enumerate(self.steps):
640
+ try:
641
+ step_outputs_for_step = []
642
+
643
+ # Create child index for each step within condition
644
+ if step_index is None or isinstance(step_index, int):
645
+ # Condition is a main step - child steps get x.1, x.2, x.3 format
646
+ child_step_index = (step_index if step_index is not None else 1, i)
647
+ else:
648
+ # Condition is already a child step - child steps get same parent number: x.y, x.y, x.y
649
+ child_step_index = step_index
650
+
651
+ # Stream step execution - mirroring Loop logic
652
+ async for event in step.aexecute_stream( # type: ignore[union-attr]
653
+ current_step_input,
654
+ session_id=session_id,
655
+ user_id=user_id,
656
+ stream_events=stream_events,
657
+ stream_executor_events=stream_executor_events,
658
+ workflow_run_response=workflow_run_response,
659
+ step_index=child_step_index,
660
+ store_executor_outputs=store_executor_outputs,
661
+ run_context=run_context,
662
+ session_state=session_state,
663
+ parent_step_id=conditional_step_id,
664
+ workflow_session=workflow_session,
665
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
666
+ num_history_runs=num_history_runs,
667
+ ):
668
+ if isinstance(event, StepOutput):
669
+ step_outputs_for_step.append(event)
670
+ all_results.append(event)
671
+ else:
672
+ # Yield other events (streaming content, step events, etc.)
673
+ yield event
674
+
675
+ step_name = getattr(step, "name", f"step_{i}")
676
+ log_debug(f"Condition step {step_name} async streaming completed")
677
+
678
+ if step_outputs_for_step:
679
+ if len(step_outputs_for_step) == 1:
680
+ condition_step_outputs[step_name] = step_outputs_for_step[0]
681
+
682
+ if step_outputs_for_step[0].stop:
683
+ logger.info(f"Early termination requested by condition step {step_name}")
684
+ break
685
+
686
+ current_step_input = self._update_step_input_from_outputs(
687
+ current_step_input, step_outputs_for_step[0], condition_step_outputs
688
+ )
689
+ else:
690
+ # Use last output
691
+ condition_step_outputs[step_name] = step_outputs_for_step[-1]
692
+
693
+ if any(output.stop for output in step_outputs_for_step):
694
+ logger.info(f"Early termination requested by condition step {step_name}")
695
+ break
696
+
697
+ current_step_input = self._update_step_input_from_outputs(
698
+ current_step_input, step_outputs_for_step, condition_step_outputs
699
+ )
700
+
701
+ except Exception as e:
702
+ step_name = getattr(step, "name", f"step_{i}")
703
+ logger.error(f"Condition step {step_name} async streaming failed: {e}")
704
+ error_output = StepOutput(
705
+ step_name=step_name,
706
+ content=f"Step {step_name} failed: {str(e)}",
707
+ success=False,
708
+ error=str(e),
709
+ )
710
+ all_results.append(error_output)
711
+ break
712
+
713
+ log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
714
+
715
+ if stream_events and workflow_run_response:
716
+ # Yield condition completed event
717
+ yield ConditionExecutionCompletedEvent(
718
+ run_id=workflow_run_response.run_id or "",
719
+ workflow_name=workflow_run_response.workflow_name or "",
720
+ workflow_id=workflow_run_response.workflow_id or "",
721
+ session_id=workflow_run_response.session_id or "",
722
+ step_name=self.name,
723
+ step_index=step_index,
724
+ condition_result=True,
725
+ executed_steps=len(self.steps),
726
+ step_results=all_results,
727
+ step_id=conditional_step_id,
728
+ parent_step_id=parent_step_id,
729
+ )
730
+
731
+ yield StepOutput(
732
+ step_name=self.name,
733
+ step_id=conditional_step_id,
734
+ step_type=StepType.CONDITION,
735
+ content=f"Condition {self.name} completed with {len(all_results)} results",
736
+ success=all(result.success for result in all_results) if all_results else True,
737
+ steps=all_results,
738
+ )