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
agno/run/agent.py ADDED
@@ -0,0 +1,787 @@
1
+ from dataclasses import asdict, dataclass, field
2
+ from enum import Enum
3
+ from time import time
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from agno.media import Audio, File, Image, Video
9
+ from agno.models.message import Citations, Message
10
+ from agno.models.metrics import Metrics
11
+ from agno.models.response import ToolExecution
12
+ from agno.reasoning.step import ReasoningStep
13
+ from agno.run.base import BaseRunOutputEvent, MessageReferences, RunStatus
14
+ from agno.utils.log import logger
15
+ from agno.utils.media import (
16
+ reconstruct_audio_list,
17
+ reconstruct_files,
18
+ reconstruct_images,
19
+ reconstruct_response_audio,
20
+ reconstruct_videos,
21
+ )
22
+
23
+ if TYPE_CHECKING:
24
+ from agno.session.summary import SessionSummary
25
+
26
+
27
+ @dataclass
28
+ class RunInput:
29
+ """Container for the raw input data passed to Agent.run().
30
+
31
+ This captures the original input exactly as provided by the user,
32
+ separate from the processed messages that go to the model.
33
+
34
+ Attributes:
35
+ input_content: The literal input message/content passed to run()
36
+ images: Images directly passed to run()
37
+ videos: Videos directly passed to run()
38
+ audios: Audio files directly passed to run()
39
+ files: Files directly passed to run()
40
+ """
41
+
42
+ input_content: Union[str, List, Dict, Message, BaseModel, List[Message]]
43
+ images: Optional[Sequence[Image]] = None
44
+ videos: Optional[Sequence[Video]] = None
45
+ audios: Optional[Sequence[Audio]] = None
46
+ files: Optional[Sequence[File]] = None
47
+
48
+ def input_content_string(self) -> str:
49
+ import json
50
+
51
+ if isinstance(self.input_content, (str)):
52
+ return self.input_content
53
+ elif isinstance(self.input_content, BaseModel):
54
+ return self.input_content.model_dump_json(exclude_none=True)
55
+ elif isinstance(self.input_content, Message):
56
+ return json.dumps(self.input_content.to_dict())
57
+ elif isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], Message):
58
+ return json.dumps([m.to_dict() for m in self.input_content])
59
+ else:
60
+ return str(self.input_content)
61
+
62
+ def to_dict(self) -> Dict[str, Any]:
63
+ """Convert to dictionary representation"""
64
+ result: Dict[str, Any] = {}
65
+
66
+ if self.input_content is not None:
67
+ if isinstance(self.input_content, (str)):
68
+ result["input_content"] = self.input_content
69
+ elif isinstance(self.input_content, BaseModel):
70
+ result["input_content"] = self.input_content.model_dump(exclude_none=True)
71
+ elif isinstance(self.input_content, Message):
72
+ result["input_content"] = self.input_content.to_dict()
73
+
74
+ # Handle input_content provided as a list of Message objects
75
+ elif (
76
+ isinstance(self.input_content, list)
77
+ and self.input_content
78
+ and isinstance(self.input_content[0], Message)
79
+ ):
80
+ result["input_content"] = [m.to_dict() for m in self.input_content]
81
+
82
+ # Handle input_content provided as a list of dicts
83
+ elif (
84
+ isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], dict)
85
+ ):
86
+ for content in self.input_content:
87
+ # Handle media input
88
+ if isinstance(content, dict):
89
+ if content.get("images"):
90
+ content["images"] = [
91
+ img.to_dict() if isinstance(img, Image) else img for img in content["images"]
92
+ ]
93
+ if content.get("videos"):
94
+ content["videos"] = [
95
+ vid.to_dict() if isinstance(vid, Video) else vid for vid in content["videos"]
96
+ ]
97
+ if content.get("audios"):
98
+ content["audios"] = [
99
+ aud.to_dict() if isinstance(aud, Audio) else aud for aud in content["audios"]
100
+ ]
101
+ if content.get("files"):
102
+ content["files"] = [
103
+ file.to_dict() if isinstance(file, File) else file for file in content["files"]
104
+ ]
105
+ result["input_content"] = self.input_content
106
+ else:
107
+ result["input_content"] = self.input_content
108
+
109
+ if self.images:
110
+ result["images"] = [img.to_dict() for img in self.images]
111
+ if self.videos:
112
+ result["videos"] = [vid.to_dict() for vid in self.videos]
113
+ if self.audios:
114
+ result["audios"] = [aud.to_dict() for aud in self.audios]
115
+ if self.files:
116
+ result["files"] = [file.to_dict() for file in self.files]
117
+
118
+ return result
119
+
120
+ @classmethod
121
+ def from_dict(cls, data: Dict[str, Any]) -> "RunInput":
122
+ """Create RunInput from dictionary"""
123
+ images = reconstruct_images(data.get("images"))
124
+ videos = reconstruct_videos(data.get("videos"))
125
+ audios = reconstruct_audio_list(data.get("audios"))
126
+ files = reconstruct_files(data.get("files"))
127
+
128
+ return cls(
129
+ input_content=data.get("input_content", ""), images=images, videos=videos, audios=audios, files=files
130
+ )
131
+
132
+
133
+ class RunEvent(str, Enum):
134
+ """Events that can be sent by the run() functions"""
135
+
136
+ run_started = "RunStarted"
137
+ run_content = "RunContent"
138
+ run_content_completed = "RunContentCompleted"
139
+ run_intermediate_content = "RunIntermediateContent"
140
+ run_completed = "RunCompleted"
141
+ run_error = "RunError"
142
+ run_cancelled = "RunCancelled"
143
+
144
+ run_paused = "RunPaused"
145
+ run_continued = "RunContinued"
146
+
147
+ pre_hook_started = "PreHookStarted"
148
+ pre_hook_completed = "PreHookCompleted"
149
+
150
+ post_hook_started = "PostHookStarted"
151
+ post_hook_completed = "PostHookCompleted"
152
+
153
+ tool_call_started = "ToolCallStarted"
154
+ tool_call_completed = "ToolCallCompleted"
155
+
156
+ reasoning_started = "ReasoningStarted"
157
+ reasoning_step = "ReasoningStep"
158
+ reasoning_completed = "ReasoningCompleted"
159
+
160
+ memory_update_started = "MemoryUpdateStarted"
161
+ memory_update_completed = "MemoryUpdateCompleted"
162
+
163
+ session_summary_started = "SessionSummaryStarted"
164
+ session_summary_completed = "SessionSummaryCompleted"
165
+
166
+ parser_model_response_started = "ParserModelResponseStarted"
167
+ parser_model_response_completed = "ParserModelResponseCompleted"
168
+
169
+ output_model_response_started = "OutputModelResponseStarted"
170
+ output_model_response_completed = "OutputModelResponseCompleted"
171
+
172
+ custom_event = "CustomEvent"
173
+
174
+
175
+ @dataclass
176
+ class BaseAgentRunEvent(BaseRunOutputEvent):
177
+ created_at: int = field(default_factory=lambda: int(time()))
178
+ event: str = ""
179
+ agent_id: str = ""
180
+ agent_name: str = ""
181
+ run_id: Optional[str] = None
182
+ parent_run_id: Optional[str] = None
183
+ session_id: Optional[str] = None
184
+
185
+ # Step context for workflow execution
186
+ workflow_id: Optional[str] = None
187
+ workflow_run_id: Optional[str] = None
188
+ step_id: Optional[str] = None
189
+ step_name: Optional[str] = None
190
+ step_index: Optional[int] = None
191
+ tools: Optional[List[ToolExecution]] = None
192
+
193
+ # For backwards compatibility
194
+ content: Optional[Any] = None
195
+
196
+ @property
197
+ def tools_requiring_confirmation(self):
198
+ return [t for t in self.tools if t.requires_confirmation] if self.tools else []
199
+
200
+ @property
201
+ def tools_requiring_user_input(self):
202
+ return [t for t in self.tools if t.requires_user_input] if self.tools else []
203
+
204
+ @property
205
+ def tools_awaiting_external_execution(self):
206
+ return [t for t in self.tools if t.external_execution_required] if self.tools else []
207
+
208
+
209
+ @dataclass
210
+ class RunStartedEvent(BaseAgentRunEvent):
211
+ """Event sent when the run starts"""
212
+
213
+ event: str = RunEvent.run_started.value
214
+ model: str = ""
215
+ model_provider: str = ""
216
+
217
+
218
+ @dataclass
219
+ class RunContentEvent(BaseAgentRunEvent):
220
+ """Main event for each delta of the RunOutput"""
221
+
222
+ event: str = RunEvent.run_content.value
223
+ content: Optional[Any] = None
224
+ workflow_agent: bool = (
225
+ False # Used by consumers of the events to distinguish between workflow agent and regular agent
226
+ )
227
+ content_type: str = "str"
228
+ reasoning_content: Optional[str] = None
229
+ model_provider_data: Optional[Dict[str, Any]] = None
230
+ citations: Optional[Citations] = None
231
+ response_audio: Optional[Audio] = None # Model audio response
232
+ image: Optional[Image] = None # Image attached to the response
233
+ references: Optional[List[MessageReferences]] = None
234
+ additional_input: Optional[List[Message]] = None
235
+ reasoning_steps: Optional[List[ReasoningStep]] = None
236
+ reasoning_messages: Optional[List[Message]] = None
237
+
238
+
239
+ @dataclass
240
+ class RunContentCompletedEvent(BaseAgentRunEvent):
241
+ event: str = RunEvent.run_content_completed.value
242
+
243
+
244
+ @dataclass
245
+ class IntermediateRunContentEvent(BaseAgentRunEvent):
246
+ event: str = RunEvent.run_intermediate_content.value
247
+ content: Optional[Any] = None
248
+ content_type: str = "str"
249
+
250
+
251
+ @dataclass
252
+ class RunCompletedEvent(BaseAgentRunEvent):
253
+ event: str = RunEvent.run_completed.value
254
+ content: Optional[Any] = None
255
+ content_type: str = "str"
256
+ reasoning_content: Optional[str] = None
257
+ citations: Optional[Citations] = None
258
+ model_provider_data: Optional[Dict[str, Any]] = None
259
+ images: Optional[List[Image]] = None # Images attached to the response
260
+ videos: Optional[List[Video]] = None # Videos attached to the response
261
+ audio: Optional[List[Audio]] = None # Audio attached to the response
262
+ response_audio: Optional[Audio] = None # Model audio response
263
+ references: Optional[List[MessageReferences]] = None
264
+ additional_input: Optional[List[Message]] = None
265
+ reasoning_steps: Optional[List[ReasoningStep]] = None
266
+ reasoning_messages: Optional[List[Message]] = None
267
+ metadata: Optional[Dict[str, Any]] = None
268
+ metrics: Optional[Metrics] = None
269
+ session_state: Optional[Dict[str, Any]] = None
270
+
271
+
272
+ @dataclass
273
+ class RunPausedEvent(BaseAgentRunEvent):
274
+ event: str = RunEvent.run_paused.value
275
+ tools: Optional[List[ToolExecution]] = None
276
+
277
+ @property
278
+ def is_paused(self):
279
+ return True
280
+
281
+
282
+ @dataclass
283
+ class RunContinuedEvent(BaseAgentRunEvent):
284
+ event: str = RunEvent.run_continued.value
285
+
286
+
287
+ @dataclass
288
+ class RunErrorEvent(BaseAgentRunEvent):
289
+ event: str = RunEvent.run_error.value
290
+ content: Optional[str] = None
291
+
292
+ # From exceptions
293
+ error_type: Optional[str] = None
294
+ error_id: Optional[str] = None
295
+ additional_data: Optional[Dict[str, Any]] = None
296
+
297
+
298
+ @dataclass
299
+ class RunCancelledEvent(BaseAgentRunEvent):
300
+ event: str = RunEvent.run_cancelled.value
301
+ reason: Optional[str] = None
302
+
303
+ @property
304
+ def is_cancelled(self):
305
+ return True
306
+
307
+
308
+ @dataclass
309
+ class PreHookStartedEvent(BaseAgentRunEvent):
310
+ event: str = RunEvent.pre_hook_started.value
311
+ pre_hook_name: Optional[str] = None
312
+ run_input: Optional[RunInput] = None
313
+
314
+
315
+ @dataclass
316
+ class PreHookCompletedEvent(BaseAgentRunEvent):
317
+ event: str = RunEvent.pre_hook_completed.value
318
+ pre_hook_name: Optional[str] = None
319
+ run_input: Optional[RunInput] = None
320
+
321
+
322
+ @dataclass
323
+ class PostHookStartedEvent(BaseAgentRunEvent):
324
+ event: str = RunEvent.post_hook_started.value
325
+ post_hook_name: Optional[str] = None
326
+
327
+
328
+ @dataclass
329
+ class PostHookCompletedEvent(BaseAgentRunEvent):
330
+ event: str = RunEvent.post_hook_completed.value
331
+ post_hook_name: Optional[str] = None
332
+
333
+
334
+ @dataclass
335
+ class MemoryUpdateStartedEvent(BaseAgentRunEvent):
336
+ event: str = RunEvent.memory_update_started.value
337
+
338
+
339
+ @dataclass
340
+ class MemoryUpdateCompletedEvent(BaseAgentRunEvent):
341
+ event: str = RunEvent.memory_update_completed.value
342
+
343
+
344
+ @dataclass
345
+ class SessionSummaryStartedEvent(BaseAgentRunEvent):
346
+ event: str = RunEvent.session_summary_started.value
347
+
348
+
349
+ @dataclass
350
+ class SessionSummaryCompletedEvent(BaseAgentRunEvent):
351
+ event: str = RunEvent.session_summary_completed.value
352
+ session_summary: Optional["SessionSummary"] = None
353
+
354
+
355
+ @dataclass
356
+ class ReasoningStartedEvent(BaseAgentRunEvent):
357
+ event: str = RunEvent.reasoning_started.value
358
+
359
+
360
+ @dataclass
361
+ class ReasoningStepEvent(BaseAgentRunEvent):
362
+ event: str = RunEvent.reasoning_step.value
363
+ content: Optional[Any] = None
364
+ content_type: str = "str"
365
+ reasoning_content: str = ""
366
+
367
+
368
+ @dataclass
369
+ class ReasoningCompletedEvent(BaseAgentRunEvent):
370
+ event: str = RunEvent.reasoning_completed.value
371
+ content: Optional[Any] = None
372
+ content_type: str = "str"
373
+
374
+
375
+ @dataclass
376
+ class ToolCallStartedEvent(BaseAgentRunEvent):
377
+ event: str = RunEvent.tool_call_started.value
378
+ tool: Optional[ToolExecution] = None
379
+
380
+
381
+ @dataclass
382
+ class ToolCallCompletedEvent(BaseAgentRunEvent):
383
+ event: str = RunEvent.tool_call_completed.value
384
+ tool: Optional[ToolExecution] = None
385
+ content: Optional[Any] = None
386
+ images: Optional[List[Image]] = None # Images produced by the tool call
387
+ videos: Optional[List[Video]] = None # Videos produced by the tool call
388
+ audio: Optional[List[Audio]] = None # Audio produced by the tool call
389
+
390
+
391
+ @dataclass
392
+ class ParserModelResponseStartedEvent(BaseAgentRunEvent):
393
+ event: str = RunEvent.parser_model_response_started.value
394
+
395
+
396
+ @dataclass
397
+ class ParserModelResponseCompletedEvent(BaseAgentRunEvent):
398
+ event: str = RunEvent.parser_model_response_completed.value
399
+
400
+
401
+ @dataclass
402
+ class OutputModelResponseStartedEvent(BaseAgentRunEvent):
403
+ event: str = RunEvent.output_model_response_started.value
404
+
405
+
406
+ @dataclass
407
+ class OutputModelResponseCompletedEvent(BaseAgentRunEvent):
408
+ event: str = RunEvent.output_model_response_completed.value
409
+
410
+
411
+ @dataclass
412
+ class CustomEvent(BaseAgentRunEvent):
413
+ event: str = RunEvent.custom_event.value
414
+
415
+ def __init__(self, **kwargs):
416
+ # Store arbitrary attributes directly on the instance
417
+ for key, value in kwargs.items():
418
+ setattr(self, key, value)
419
+
420
+
421
+ RunOutputEvent = Union[
422
+ RunStartedEvent,
423
+ RunContentEvent,
424
+ IntermediateRunContentEvent,
425
+ RunContentCompletedEvent,
426
+ RunCompletedEvent,
427
+ RunErrorEvent,
428
+ RunCancelledEvent,
429
+ RunPausedEvent,
430
+ RunContinuedEvent,
431
+ PreHookStartedEvent,
432
+ PreHookCompletedEvent,
433
+ PostHookStartedEvent,
434
+ PostHookCompletedEvent,
435
+ ReasoningStartedEvent,
436
+ ReasoningStepEvent,
437
+ ReasoningCompletedEvent,
438
+ MemoryUpdateStartedEvent,
439
+ MemoryUpdateCompletedEvent,
440
+ SessionSummaryStartedEvent,
441
+ SessionSummaryCompletedEvent,
442
+ ToolCallStartedEvent,
443
+ ToolCallCompletedEvent,
444
+ ParserModelResponseStartedEvent,
445
+ ParserModelResponseCompletedEvent,
446
+ OutputModelResponseStartedEvent,
447
+ OutputModelResponseCompletedEvent,
448
+ CustomEvent,
449
+ ]
450
+
451
+
452
+ # Map event string to dataclass
453
+ RUN_EVENT_TYPE_REGISTRY = {
454
+ RunEvent.run_started.value: RunStartedEvent,
455
+ RunEvent.run_content.value: RunContentEvent,
456
+ RunEvent.run_content_completed.value: RunContentCompletedEvent,
457
+ RunEvent.run_intermediate_content.value: IntermediateRunContentEvent,
458
+ RunEvent.run_completed.value: RunCompletedEvent,
459
+ RunEvent.run_error.value: RunErrorEvent,
460
+ RunEvent.run_cancelled.value: RunCancelledEvent,
461
+ RunEvent.run_paused.value: RunPausedEvent,
462
+ RunEvent.run_continued.value: RunContinuedEvent,
463
+ RunEvent.pre_hook_started.value: PreHookStartedEvent,
464
+ RunEvent.pre_hook_completed.value: PreHookCompletedEvent,
465
+ RunEvent.post_hook_started.value: PostHookStartedEvent,
466
+ RunEvent.post_hook_completed.value: PostHookCompletedEvent,
467
+ RunEvent.reasoning_started.value: ReasoningStartedEvent,
468
+ RunEvent.reasoning_step.value: ReasoningStepEvent,
469
+ RunEvent.reasoning_completed.value: ReasoningCompletedEvent,
470
+ RunEvent.memory_update_started.value: MemoryUpdateStartedEvent,
471
+ RunEvent.memory_update_completed.value: MemoryUpdateCompletedEvent,
472
+ RunEvent.session_summary_started.value: SessionSummaryStartedEvent,
473
+ RunEvent.session_summary_completed.value: SessionSummaryCompletedEvent,
474
+ RunEvent.tool_call_started.value: ToolCallStartedEvent,
475
+ RunEvent.tool_call_completed.value: ToolCallCompletedEvent,
476
+ RunEvent.parser_model_response_started.value: ParserModelResponseStartedEvent,
477
+ RunEvent.parser_model_response_completed.value: ParserModelResponseCompletedEvent,
478
+ RunEvent.output_model_response_started.value: OutputModelResponseStartedEvent,
479
+ RunEvent.output_model_response_completed.value: OutputModelResponseCompletedEvent,
480
+ RunEvent.custom_event.value: CustomEvent,
481
+ }
482
+
483
+
484
+ def run_output_event_from_dict(data: dict) -> BaseRunOutputEvent:
485
+ event_type = data.get("event", "")
486
+ cls = RUN_EVENT_TYPE_REGISTRY.get(event_type)
487
+ if not cls:
488
+ raise ValueError(f"Unknown event type: {event_type}")
489
+ return cls.from_dict(data) # type: ignore
490
+
491
+
492
+ @dataclass
493
+ class RunOutput:
494
+ """Response returned by Agent.run() or Workflow.run() functions"""
495
+
496
+ run_id: Optional[str] = None
497
+ agent_id: Optional[str] = None
498
+ agent_name: Optional[str] = None
499
+ session_id: Optional[str] = None
500
+ parent_run_id: Optional[str] = None
501
+ workflow_id: Optional[str] = None
502
+ user_id: Optional[str] = None
503
+
504
+ # Input media and messages from user
505
+ input: Optional[RunInput] = None
506
+
507
+ content: Optional[Any] = None
508
+ content_type: str = "str"
509
+
510
+ reasoning_content: Optional[str] = None
511
+ reasoning_steps: Optional[List[ReasoningStep]] = None
512
+ reasoning_messages: Optional[List[Message]] = None
513
+
514
+ model_provider_data: Optional[Dict[str, Any]] = None
515
+
516
+ model: Optional[str] = None
517
+ model_provider: Optional[str] = None
518
+ messages: Optional[List[Message]] = None
519
+ metrics: Optional[Metrics] = None
520
+ additional_input: Optional[List[Message]] = None
521
+
522
+ tools: Optional[List[ToolExecution]] = None
523
+
524
+ images: Optional[List[Image]] = None # Images attached to the response
525
+ videos: Optional[List[Video]] = None # Videos attached to the response
526
+ audio: Optional[List[Audio]] = None # Audio attached to the response
527
+ files: Optional[List[File]] = None # Files attached to the response
528
+ response_audio: Optional[Audio] = None # Model audio response
529
+
530
+ citations: Optional[Citations] = None
531
+ references: Optional[List[MessageReferences]] = None
532
+
533
+ metadata: Optional[Dict[str, Any]] = None
534
+ session_state: Optional[Dict[str, Any]] = None
535
+
536
+ created_at: int = field(default_factory=lambda: int(time()))
537
+
538
+ events: Optional[List[RunOutputEvent]] = None
539
+
540
+ status: RunStatus = RunStatus.running
541
+
542
+ # === FOREIGN KEY RELATIONSHIPS ===
543
+ # These fields establish relationships to parent workflow/step structures
544
+ # and should be treated as foreign keys for data integrity
545
+ workflow_step_id: Optional[str] = None # FK: Points to StepOutput.step_id
546
+
547
+ @property
548
+ def is_paused(self):
549
+ return self.status == RunStatus.paused
550
+
551
+ @property
552
+ def is_cancelled(self):
553
+ return self.status == RunStatus.cancelled
554
+
555
+ @property
556
+ def tools_requiring_confirmation(self):
557
+ return [t for t in self.tools if t.requires_confirmation] if self.tools else []
558
+
559
+ @property
560
+ def tools_requiring_user_input(self):
561
+ return [t for t in self.tools if t.requires_user_input] if self.tools else []
562
+
563
+ @property
564
+ def tools_awaiting_external_execution(self):
565
+ return [t for t in self.tools if t.external_execution_required] if self.tools else []
566
+
567
+ def to_dict(self) -> Dict[str, Any]:
568
+ _dict = {
569
+ k: v
570
+ for k, v in asdict(self).items()
571
+ if v is not None
572
+ and k
573
+ not in [
574
+ "messages",
575
+ "tools",
576
+ "metadata",
577
+ "images",
578
+ "videos",
579
+ "audio",
580
+ "files",
581
+ "response_audio",
582
+ "input",
583
+ "citations",
584
+ "events",
585
+ "additional_input",
586
+ "reasoning_steps",
587
+ "reasoning_messages",
588
+ "references",
589
+ ]
590
+ }
591
+
592
+ if self.metrics is not None:
593
+ _dict["metrics"] = self.metrics.to_dict() if isinstance(self.metrics, Metrics) else self.metrics
594
+
595
+ if self.events is not None:
596
+ _dict["events"] = [e.to_dict() for e in self.events]
597
+
598
+ if self.status is not None:
599
+ _dict["status"] = self.status.value if isinstance(self.status, RunStatus) else self.status
600
+
601
+ if self.messages is not None:
602
+ _dict["messages"] = [m.to_dict() for m in self.messages]
603
+
604
+ if self.metadata is not None:
605
+ _dict["metadata"] = self.metadata
606
+
607
+ if self.additional_input is not None:
608
+ _dict["additional_input"] = [m.to_dict() for m in self.additional_input]
609
+
610
+ if self.reasoning_messages is not None:
611
+ _dict["reasoning_messages"] = [m.to_dict() for m in self.reasoning_messages]
612
+
613
+ if self.reasoning_steps is not None:
614
+ _dict["reasoning_steps"] = [rs.model_dump() for rs in self.reasoning_steps]
615
+
616
+ if self.references is not None:
617
+ _dict["references"] = [r.model_dump() for r in self.references]
618
+
619
+ if self.images is not None:
620
+ _dict["images"] = []
621
+ for img in self.images:
622
+ if isinstance(img, Image):
623
+ _dict["images"].append(img.to_dict())
624
+ else:
625
+ _dict["images"].append(img)
626
+
627
+ if self.videos is not None:
628
+ _dict["videos"] = []
629
+ for vid in self.videos:
630
+ if isinstance(vid, Video):
631
+ _dict["videos"].append(vid.to_dict())
632
+ else:
633
+ _dict["videos"].append(vid)
634
+
635
+ if self.audio is not None:
636
+ _dict["audio"] = []
637
+ for aud in self.audio:
638
+ if isinstance(aud, Audio):
639
+ _dict["audio"].append(aud.to_dict())
640
+ else:
641
+ _dict["audio"].append(aud)
642
+
643
+ if self.files is not None:
644
+ _dict["files"] = []
645
+ for file in self.files:
646
+ if isinstance(file, File):
647
+ _dict["files"].append(file.to_dict())
648
+ else:
649
+ _dict["files"].append(file)
650
+
651
+ if self.response_audio is not None:
652
+ if isinstance(self.response_audio, Audio):
653
+ _dict["response_audio"] = self.response_audio.to_dict()
654
+ else:
655
+ _dict["response_audio"] = self.response_audio
656
+
657
+ if self.citations is not None:
658
+ if isinstance(self.citations, Citations):
659
+ _dict["citations"] = self.citations.model_dump(exclude_none=True)
660
+ else:
661
+ _dict["citations"] = self.citations
662
+
663
+ if self.content and isinstance(self.content, BaseModel):
664
+ _dict["content"] = self.content.model_dump(exclude_none=True, mode="json")
665
+
666
+ if self.tools is not None:
667
+ _dict["tools"] = []
668
+ for tool in self.tools:
669
+ if isinstance(tool, ToolExecution):
670
+ _dict["tools"].append(tool.to_dict())
671
+ else:
672
+ _dict["tools"].append(tool)
673
+
674
+ if self.input is not None:
675
+ _dict["input"] = self.input.to_dict()
676
+
677
+ return _dict
678
+
679
+ def to_json(self, separators=(", ", ": "), indent: Optional[int] = 2) -> str:
680
+ import json
681
+
682
+ try:
683
+ _dict = self.to_dict()
684
+ except Exception:
685
+ logger.error("Failed to convert response to json", exc_info=True)
686
+ raise
687
+
688
+ if indent is None:
689
+ return json.dumps(_dict, separators=separators)
690
+ else:
691
+ return json.dumps(_dict, indent=indent, separators=separators)
692
+
693
+ @classmethod
694
+ def from_dict(cls, data: Dict[str, Any]) -> "RunOutput":
695
+ if "run" in data:
696
+ data = data.pop("run")
697
+
698
+ events = data.pop("events", None)
699
+ final_events = []
700
+ for event in events or []:
701
+ if "agent_id" in event:
702
+ event = run_output_event_from_dict(event)
703
+ else:
704
+ # Use the factory from response.py for agent events
705
+ from agno.run.team import team_run_output_event_from_dict
706
+
707
+ event = team_run_output_event_from_dict(event)
708
+ final_events.append(event)
709
+ events = final_events
710
+
711
+ messages = data.pop("messages", None)
712
+ messages = [Message.from_dict(message) for message in messages] if messages else None
713
+
714
+ citations = data.pop("citations", None)
715
+ citations = Citations.model_validate(citations) if citations else None
716
+
717
+ tools = data.pop("tools", [])
718
+ tools = [ToolExecution.from_dict(tool) for tool in tools] if tools else None
719
+
720
+ images = reconstruct_images(data.pop("images", []))
721
+ videos = reconstruct_videos(data.pop("videos", []))
722
+ audio = reconstruct_audio_list(data.pop("audio", []))
723
+ files = reconstruct_files(data.pop("files", []))
724
+ response_audio = reconstruct_response_audio(data.pop("response_audio", None))
725
+
726
+ input_data = data.pop("input", None)
727
+ input_obj = None
728
+ if input_data:
729
+ input_obj = RunInput.from_dict(input_data)
730
+
731
+ metrics = data.pop("metrics", None)
732
+ if metrics:
733
+ metrics = Metrics(**metrics)
734
+
735
+ additional_input = data.pop("additional_input", None)
736
+
737
+ if additional_input is not None:
738
+ additional_input = [Message.from_dict(message) for message in additional_input]
739
+
740
+ reasoning_steps = data.pop("reasoning_steps", None)
741
+ if reasoning_steps is not None:
742
+ reasoning_steps = [ReasoningStep.model_validate(step) for step in reasoning_steps]
743
+
744
+ reasoning_messages = data.pop("reasoning_messages", None)
745
+ if reasoning_messages is not None:
746
+ reasoning_messages = [Message.from_dict(message) for message in reasoning_messages]
747
+
748
+ references = data.pop("references", None)
749
+ if references is not None:
750
+ references = [MessageReferences.model_validate(reference) for reference in references]
751
+
752
+ # Filter data to only include fields that are actually defined in the RunOutput dataclass
753
+ from dataclasses import fields
754
+
755
+ supported_fields = {f.name for f in fields(cls)}
756
+ filtered_data = {k: v for k, v in data.items() if k in supported_fields}
757
+
758
+ return cls(
759
+ messages=messages,
760
+ metrics=metrics,
761
+ citations=citations,
762
+ tools=tools,
763
+ images=images,
764
+ audio=audio,
765
+ videos=videos,
766
+ files=files,
767
+ response_audio=response_audio,
768
+ input=input_obj,
769
+ events=events,
770
+ additional_input=additional_input,
771
+ reasoning_steps=reasoning_steps,
772
+ reasoning_messages=reasoning_messages,
773
+ references=references,
774
+ **filtered_data,
775
+ )
776
+
777
+ def get_content_as_string(self, **kwargs) -> str:
778
+ import json
779
+
780
+ from pydantic import BaseModel
781
+
782
+ if isinstance(self.content, str):
783
+ return self.content
784
+ elif isinstance(self.content, BaseModel):
785
+ return self.content.model_dump_json(exclude_none=True, **kwargs)
786
+ else:
787
+ return json.dumps(self.content, **kwargs)