agno 1.8.1__py3-none-any.whl → 2.0.0__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 (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +11 -66
  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/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1743 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1432 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +882 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1045 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1416 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +15 -11
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1551 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +46 -151
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +85 -47
  158. agno/models/openai/chat.py +154 -37
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +15 -9
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +497 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +77 -33
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +32 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -2,20 +2,21 @@ import asyncio
2
2
  from concurrent.futures import ThreadPoolExecutor, as_completed
3
3
  from dataclasses import dataclass
4
4
  from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Iterator, List, Optional, Union
5
+ from uuid import uuid4
5
6
 
6
- from agno.run.response import RunResponseEvent
7
- from agno.run.team import TeamRunResponseEvent
8
- from agno.run.v2.workflow import (
7
+ from agno.models.metrics import Metrics
8
+ from agno.run.agent import RunOutputEvent
9
+ from agno.run.team import TeamRunOutputEvent
10
+ from agno.run.workflow import (
9
11
  ParallelExecutionCompletedEvent,
10
12
  ParallelExecutionStartedEvent,
11
- WorkflowRunResponse,
12
- WorkflowRunResponseEvent,
13
+ WorkflowRunOutput,
14
+ WorkflowRunOutputEvent,
13
15
  )
14
16
  from agno.utils.log import log_debug, logger
15
- from agno.workflow.v2.condition import Condition
16
- from agno.workflow.v2.step import Step
17
- from agno.workflow.v2.steps import Steps
18
- from agno.workflow.v2.types import StepInput, StepOutput
17
+ from agno.workflow.condition import Condition
18
+ from agno.workflow.step import Step
19
+ from agno.workflow.types import StepInput, StepOutput, StepType
19
20
 
20
21
  WorkflowSteps = List[
21
22
  Union[
@@ -55,10 +56,10 @@ class Parallel:
55
56
  """Prepare the steps for execution - mirrors workflow logic"""
56
57
  from agno.agent.agent import Agent
57
58
  from agno.team.team import Team
58
- from agno.workflow.v2.loop import Loop
59
- from agno.workflow.v2.router import Router
60
- from agno.workflow.v2.step import Step
61
- from agno.workflow.v2.steps import Steps
59
+ from agno.workflow.loop import Loop
60
+ from agno.workflow.router import Router
61
+ from agno.workflow.step import Step
62
+ from agno.workflow.steps import Steps
62
63
 
63
64
  prepared_steps: WorkflowSteps = []
64
65
  for step in self.steps:
@@ -78,23 +79,25 @@ class Parallel:
78
79
  def _aggregate_results(self, step_outputs: List[StepOutput]) -> StepOutput:
79
80
  """Aggregate multiple step outputs into a single StepOutput"""
80
81
  if not step_outputs:
81
- return StepOutput(step_name=self.name or "Parallel", content="No parallel steps executed")
82
-
83
- # To store the individual step outputs for each parallel step
84
- parallel_step_outputs = {output.step_name or f"step_{i}": output for i, output in enumerate(step_outputs)}
82
+ return StepOutput(
83
+ step_name=self.name or "Parallel",
84
+ step_id=str(uuid4()),
85
+ step_type="Parallel",
86
+ content="No parallel steps executed",
87
+ steps=[],
88
+ )
85
89
 
86
90
  if len(step_outputs) == 1:
87
- # Single result, update the step name but preserve parallel structure
91
+ # Single result, but still create a Parallel container
88
92
  single_result = step_outputs[0]
89
-
90
- # Extract metrics using the dedicated method
91
93
  aggregated_metrics = self._extract_metrics_from_response(step_outputs)
92
94
 
93
95
  return StepOutput(
94
96
  step_name=self.name or "Parallel",
95
- content=single_result.content,
96
- parallel_step_outputs=parallel_step_outputs,
97
- response=single_result.response,
97
+ step_id=str(uuid4()),
98
+ step_type=StepType.PARALLEL,
99
+ content=f"Parallel {self.name or 'execution'} completed with 1 result",
100
+ executor_name=self.name or "Parallel",
98
101
  images=single_result.images,
99
102
  videos=single_result.videos,
100
103
  audio=single_result.audio,
@@ -102,12 +105,13 @@ class Parallel:
102
105
  success=single_result.success,
103
106
  error=single_result.error,
104
107
  stop=single_result.stop,
108
+ steps=step_outputs, # This is the key addition
105
109
  )
106
110
 
107
111
  early_termination_requested = any(output.stop for output in step_outputs if hasattr(output, "stop"))
108
112
 
109
113
  # Multiple results - aggregate them
110
- aggregated_content = self._build_aggregated_content(step_outputs)
114
+ aggregated_content = f"Parallel {self.name or 'execution'} completed with {len(step_outputs)} results"
111
115
 
112
116
  # Combine all media from parallel steps
113
117
  all_images = []
@@ -127,63 +131,42 @@ class Parallel:
127
131
 
128
132
  return StepOutput(
129
133
  step_name=self.name or "Parallel",
134
+ step_id=str(uuid4()),
135
+ step_type=StepType.PARALLEL,
136
+ executor_type="parallel",
137
+ executor_name=self.name or "Parallel",
130
138
  content=aggregated_content,
131
- parallel_step_outputs=parallel_step_outputs,
132
139
  images=all_images if all_images else None,
133
140
  videos=all_videos if all_videos else None,
134
141
  audio=all_audio if all_audio else None,
135
142
  success=not has_any_failure,
136
143
  stop=early_termination_requested,
137
144
  metrics=aggregated_metrics,
145
+ steps=step_outputs,
138
146
  )
139
147
 
140
- def _extract_metrics_from_response(self, step_outputs: List[StepOutput]) -> Optional[Dict[str, Any]]:
148
+ def _extract_metrics_from_response(self, step_outputs: List[StepOutput]) -> Optional[Metrics]:
141
149
  """Extract and aggregate metrics from parallel step outputs"""
142
150
  if not step_outputs:
143
151
  return None
144
152
 
145
- parallel_step_metrics = {}
153
+ # Aggregate metrics from all parallel step outputs
154
+ total_metrics = Metrics()
146
155
 
147
156
  for result in step_outputs:
148
- step_name = result.step_name or "unknown"
149
-
150
- # Create clean step metrics for parallel steps
151
157
  if result.metrics:
152
- # If the step already has structured metrics, extract the actual metrics
153
- if isinstance(result.metrics, dict) and "metrics" in result.metrics:
154
- actual_metrics = result.metrics.get("metrics")
155
- executor_type = result.metrics.get("executor_type", "unknown")
156
- executor_name = result.metrics.get("executor_name", "unknown")
157
- else:
158
- actual_metrics = result.metrics
159
- executor_type = getattr(result, "executor_type", "unknown")
160
- executor_name = getattr(result, "executor_name", "unknown")
161
-
162
- parallel_step_metrics[step_name] = {
163
- "step_name": step_name,
164
- "executor_type": executor_type,
165
- "executor_name": executor_name,
166
- "metrics": actual_metrics,
167
- }
168
- else:
169
- # Even if no metrics, record the step execution
170
- parallel_step_metrics[step_name] = {
171
- "step_name": step_name,
172
- "executor_type": getattr(result, "executor_type", "unknown"),
173
- "executor_name": getattr(result, "executor_name", "unknown"),
174
- "metrics": None,
175
- }
176
-
177
- # Create aggregated metrics structure for parallel execution
178
- if parallel_step_metrics:
179
- return {
180
- "step_name": self.name or "Parallel",
181
- "executor_type": "parallel",
182
- "executor_name": self.name or "Parallel",
183
- "parallel_steps": parallel_step_metrics,
184
- }
158
+ total_metrics = total_metrics + result.metrics
159
+
160
+ # If no metrics were found, return None
161
+ if (
162
+ total_metrics.input_tokens == 0
163
+ and total_metrics.output_tokens == 0
164
+ and total_metrics.total_tokens == 0
165
+ and total_metrics.duration is None
166
+ ):
167
+ return None
185
168
 
186
- return None
169
+ return total_metrics
187
170
 
188
171
  def _build_aggregated_content(self, step_outputs: List[StepOutput]) -> str:
189
172
  """Build aggregated content from multiple step outputs"""
@@ -212,6 +195,9 @@ class Parallel:
212
195
  step_input: StepInput,
213
196
  session_id: Optional[str] = None,
214
197
  user_id: Optional[str] = None,
198
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
199
+ store_executor_outputs: bool = True,
200
+ session_state: Optional[Dict[str, Any]] = None,
215
201
  ) -> StepOutput:
216
202
  """Execute all steps in parallel and return aggregated result"""
217
203
  # Use workflow logger for parallel orchestration
@@ -221,17 +207,27 @@ class Parallel:
221
207
 
222
208
  def execute_step_with_index(step_with_index):
223
209
  """Execute a single step and preserve its original index"""
224
- index, step = step_with_index
210
+ idx, step = step_with_index
225
211
  try:
226
- result = step.execute(step_input, session_id=session_id, user_id=user_id) # type: ignore[union-attr]
227
- return (index, result)
228
- except Exception as e:
229
- step_name = getattr(step, "name", f"step_{index}")
230
- logger.error(f"Parallel step {step_name} failed: {e}")
212
+ step_result = step.execute(
213
+ step_input,
214
+ session_id=session_id,
215
+ user_id=user_id,
216
+ workflow_run_response=workflow_run_response,
217
+ store_executor_outputs=store_executor_outputs,
218
+ session_state=session_state,
219
+ ) # type: ignore[union-attr]
220
+ return idx, step_result
221
+ except Exception as exc:
222
+ parallel_step_name = getattr(step, "name", f"step_{idx}")
223
+ logger.error(f"Parallel step {parallel_step_name} failed: {exc}")
231
224
  return (
232
- index,
225
+ idx,
233
226
  StepOutput(
234
- step_name=step_name, content=f"Step {step_name} failed: {str(e)}", success=False, error=str(e)
227
+ step_name=parallel_step_name,
228
+ content=f"Step {parallel_step_name} failed: {str(exc)}",
229
+ success=False,
230
+ error=str(exc),
235
231
  ),
236
232
  )
237
233
 
@@ -295,12 +291,17 @@ class Parallel:
295
291
  session_id: Optional[str] = None,
296
292
  user_id: Optional[str] = None,
297
293
  stream_intermediate_steps: bool = False,
298
- workflow_run_response: Optional[WorkflowRunResponse] = None,
294
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
299
295
  step_index: Optional[Union[int, tuple]] = None,
300
- ) -> Iterator[Union[WorkflowRunResponseEvent, StepOutput]]:
296
+ store_executor_outputs: bool = True,
297
+ session_state: Optional[Dict[str, Any]] = None,
298
+ parent_step_id: Optional[str] = None,
299
+ ) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
301
300
  """Execute all steps in parallel with streaming support"""
302
301
  log_debug(f"Parallel Start: {self.name} ({len(self.steps)} steps)", center=True, symbol="=")
303
302
 
303
+ parallel_step_id = str(uuid4())
304
+
304
305
  self._prepare_steps()
305
306
 
306
307
  if stream_intermediate_steps and workflow_run_response:
@@ -313,19 +314,21 @@ class Parallel:
313
314
  step_name=self.name,
314
315
  step_index=step_index,
315
316
  parallel_step_count=len(self.steps),
317
+ step_id=parallel_step_id,
318
+ parent_step_id=parent_step_id,
316
319
  )
317
320
 
318
321
  def execute_step_stream_with_index(step_with_index):
319
322
  """Execute a single step with streaming and preserve its original index"""
320
- index, step = step_with_index
323
+ idx, step = step_with_index
321
324
  try:
322
- events = []
325
+ step_events = []
323
326
 
324
327
  # If step_index is None or integer (main step): create (step_index, sub_index)
325
328
  # If step_index is tuple (child step): all parallel sub-steps get same index
326
329
  if step_index is None or isinstance(step_index, int):
327
330
  # Parallel is a main step - sub-steps get sequential numbers: 1.1, 1.2, 1.3
328
- sub_step_index = (step_index if step_index is not None else 0, index)
331
+ sub_step_index = (step_index if step_index is not None else 0, idx)
329
332
  else:
330
333
  # Parallel is a child step - all sub-steps get the same parent number: 1.1, 1.1, 1.1
331
334
  sub_step_index = step_index
@@ -338,20 +341,23 @@ class Parallel:
338
341
  stream_intermediate_steps=stream_intermediate_steps,
339
342
  workflow_run_response=workflow_run_response,
340
343
  step_index=sub_step_index,
344
+ store_executor_outputs=store_executor_outputs,
345
+ session_state=session_state,
346
+ parent_step_id=parallel_step_id,
341
347
  ):
342
- events.append(event)
343
- return (index, events)
344
- except Exception as e:
345
- step_name = getattr(step, "name", f"step_{index}")
346
- logger.error(f"Parallel step {step_name} streaming failed: {e}")
348
+ step_events.append(event)
349
+ return idx, step_events
350
+ except Exception as exc:
351
+ parallel_step_name = getattr(step, "name", f"step_{idx}")
352
+ logger.error(f"Parallel step {parallel_step_name} streaming failed: {exc}")
347
353
  return (
348
- index,
354
+ idx,
349
355
  [
350
356
  StepOutput(
351
- step_name=step_name,
352
- content=f"Step {step_name} failed: {str(e)}",
357
+ step_name=parallel_step_name,
358
+ content=f"Step {parallel_step_name} failed: {str(exc)}",
353
359
  success=False,
354
- error=str(e),
360
+ error=str(exc),
355
361
  )
356
362
  ],
357
363
  )
@@ -431,6 +437,8 @@ class Parallel:
431
437
  step_index=step_index,
432
438
  parallel_step_count=len(self.steps),
433
439
  step_results=[aggregated_result], # Now single aggregated result
440
+ step_id=parallel_step_id,
441
+ parent_step_id=parent_step_id,
434
442
  )
435
443
 
436
444
  async def aexecute(
@@ -438,6 +446,9 @@ class Parallel:
438
446
  step_input: StepInput,
439
447
  session_id: Optional[str] = None,
440
448
  user_id: Optional[str] = None,
449
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
450
+ store_executor_outputs: bool = True,
451
+ session_state: Optional[Dict[str, Any]] = None,
441
452
  ) -> StepOutput:
442
453
  """Execute all steps in parallel using asyncio and return aggregated result"""
443
454
  # Use workflow logger for async parallel orchestration
@@ -447,20 +458,27 @@ class Parallel:
447
458
 
448
459
  async def execute_step_async_with_index(step_with_index):
449
460
  """Execute a single step asynchronously and preserve its original index"""
450
- index, step = step_with_index
461
+ idx, step = step_with_index
451
462
  try:
452
- result = await step.aexecute(step_input, session_id=session_id, user_id=user_id) # type: ignore[union-attr]
453
- return (index, result)
454
- except Exception as e:
455
- step_name = getattr(step, "name", f"step_{index}")
456
- logger.error(f"Parallel step {step_name} failed: {e}")
463
+ inner_step_result = await step.aexecute(
464
+ step_input,
465
+ session_id=session_id,
466
+ user_id=user_id,
467
+ workflow_run_response=workflow_run_response,
468
+ store_executor_outputs=store_executor_outputs,
469
+ session_state=session_state,
470
+ ) # type: ignore[union-attr]
471
+ return idx, inner_step_result
472
+ except Exception as exc:
473
+ parallel_step_name = getattr(step, "name", f"step_{idx}")
474
+ logger.error(f"Parallel step {parallel_step_name} failed: {exc}")
457
475
  return (
458
- index,
476
+ idx,
459
477
  StepOutput(
460
- step_name=step_name,
461
- content=f"Step {step_name} failed: {str(e)}",
478
+ step_name=parallel_step_name,
479
+ content=f"Step {parallel_step_name} failed: {str(exc)}",
462
480
  success=False,
463
- error=str(e),
481
+ error=str(exc),
464
482
  ),
465
483
  )
466
484
 
@@ -522,12 +540,17 @@ class Parallel:
522
540
  session_id: Optional[str] = None,
523
541
  user_id: Optional[str] = None,
524
542
  stream_intermediate_steps: bool = False,
525
- workflow_run_response: Optional[WorkflowRunResponse] = None,
543
+ workflow_run_response: Optional[WorkflowRunOutput] = None,
526
544
  step_index: Optional[Union[int, tuple]] = None,
527
- ) -> AsyncIterator[Union[WorkflowRunResponseEvent, TeamRunResponseEvent, RunResponseEvent, StepOutput]]:
545
+ store_executor_outputs: bool = True,
546
+ session_state: Optional[Dict[str, Any]] = None,
547
+ parent_step_id: Optional[str] = None,
548
+ ) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
528
549
  """Execute all steps in parallel with async streaming support"""
529
550
  log_debug(f"Parallel Start: {self.name} ({len(self.steps)} steps)", center=True, symbol="=")
530
551
 
552
+ parallel_step_id = str(uuid4())
553
+
531
554
  self._prepare_steps()
532
555
 
533
556
  if stream_intermediate_steps and workflow_run_response:
@@ -540,19 +563,21 @@ class Parallel:
540
563
  step_name=self.name,
541
564
  step_index=step_index,
542
565
  parallel_step_count=len(self.steps),
566
+ step_id=parallel_step_id,
567
+ parent_step_id=parent_step_id,
543
568
  )
544
569
 
545
570
  async def execute_step_stream_async_with_index(step_with_index):
546
571
  """Execute a single step with async streaming and preserve its original index"""
547
- index, step = step_with_index
572
+ idx, step = step_with_index
548
573
  try:
549
- events = []
574
+ step_events = []
550
575
 
551
576
  # If step_index is None or integer (main step): create (step_index, sub_index)
552
577
  # If step_index is tuple (child step): all parallel sub-steps get same index
553
578
  if step_index is None or isinstance(step_index, int):
554
579
  # Parallel is a main step - sub-steps get sequential numbers: 1.1, 1.2, 1.3
555
- sub_step_index = (step_index if step_index is not None else 0, index)
580
+ sub_step_index = (step_index if step_index is not None else 0, idx)
556
581
  else:
557
582
  # Parallel is a child step - all sub-steps get the same parent number: 1.1, 1.1, 1.1
558
583
  sub_step_index = step_index
@@ -565,18 +590,21 @@ class Parallel:
565
590
  stream_intermediate_steps=stream_intermediate_steps,
566
591
  workflow_run_response=workflow_run_response,
567
592
  step_index=sub_step_index,
593
+ store_executor_outputs=store_executor_outputs,
594
+ session_state=session_state,
595
+ parent_step_id=parallel_step_id,
568
596
  ): # type: ignore[union-attr]
569
- events.append(event)
570
- return (index, events)
597
+ step_events.append(event)
598
+ return idx, step_events
571
599
  except Exception as e:
572
- step_name = getattr(step, "name", f"step_{index}")
573
- logger.error(f"Parallel step {step_name} async streaming failed: {e}")
600
+ parallel_step_name = getattr(step, "name", f"step_{idx}")
601
+ logger.error(f"Parallel step {parallel_step_name} async streaming failed: {e}")
574
602
  return (
575
- index,
603
+ idx,
576
604
  [
577
605
  StepOutput(
578
- step_name=step_name,
579
- content=f"Step {step_name} failed: {str(e)}",
606
+ step_name=parallel_step_name,
607
+ content=f"Step {parallel_step_name} failed: {str(e)}",
580
608
  success=False,
581
609
  error=str(e),
582
610
  )
@@ -656,4 +684,6 @@ class Parallel:
656
684
  step_index=step_index,
657
685
  parallel_step_count=len(self.steps),
658
686
  step_results=[aggregated_result], # Now single aggregated result
687
+ step_id=parallel_step_id,
688
+ parent_step_id=parent_step_id,
659
689
  )