agno 1.8.2__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 (589) hide show
  1. agno/agent/__init__.py +19 -27
  2. agno/agent/agent.py +3143 -4170
  3. agno/api/agent.py +11 -67
  4. agno/api/api.py +5 -46
  5. agno/api/evals.py +8 -19
  6. agno/api/os.py +17 -0
  7. agno/api/routes.py +6 -41
  8. agno/api/schemas/__init__.py +9 -0
  9. agno/api/schemas/agent.py +5 -21
  10. agno/api/schemas/evals.py +7 -16
  11. agno/api/schemas/os.py +14 -0
  12. agno/api/schemas/team.py +5 -21
  13. agno/api/schemas/utils.py +21 -0
  14. agno/api/schemas/workflows.py +11 -7
  15. agno/api/settings.py +53 -0
  16. agno/api/team.py +11 -66
  17. agno/api/workflow.py +28 -0
  18. agno/cloud/aws/base.py +214 -0
  19. agno/cloud/aws/s3/__init__.py +2 -0
  20. agno/cloud/aws/s3/api_client.py +43 -0
  21. agno/cloud/aws/s3/bucket.py +195 -0
  22. agno/cloud/aws/s3/object.py +57 -0
  23. agno/db/__init__.py +24 -0
  24. agno/db/base.py +245 -0
  25. agno/db/dynamo/__init__.py +3 -0
  26. agno/db/dynamo/dynamo.py +1743 -0
  27. agno/db/dynamo/schemas.py +278 -0
  28. agno/db/dynamo/utils.py +684 -0
  29. agno/db/firestore/__init__.py +3 -0
  30. agno/db/firestore/firestore.py +1432 -0
  31. agno/db/firestore/schemas.py +130 -0
  32. agno/db/firestore/utils.py +278 -0
  33. agno/db/gcs_json/__init__.py +3 -0
  34. agno/db/gcs_json/gcs_json_db.py +1001 -0
  35. agno/db/gcs_json/utils.py +194 -0
  36. agno/db/in_memory/__init__.py +3 -0
  37. agno/db/in_memory/in_memory_db.py +882 -0
  38. agno/db/in_memory/utils.py +172 -0
  39. agno/db/json/__init__.py +3 -0
  40. agno/db/json/json_db.py +1045 -0
  41. agno/db/json/utils.py +196 -0
  42. agno/db/migrations/v1_to_v2.py +162 -0
  43. agno/db/mongo/__init__.py +3 -0
  44. agno/db/mongo/mongo.py +1416 -0
  45. agno/db/mongo/schemas.py +77 -0
  46. agno/db/mongo/utils.py +204 -0
  47. agno/db/mysql/__init__.py +3 -0
  48. agno/db/mysql/mysql.py +1719 -0
  49. agno/db/mysql/schemas.py +124 -0
  50. agno/db/mysql/utils.py +297 -0
  51. agno/db/postgres/__init__.py +3 -0
  52. agno/db/postgres/postgres.py +1710 -0
  53. agno/db/postgres/schemas.py +124 -0
  54. agno/db/postgres/utils.py +280 -0
  55. agno/db/redis/__init__.py +3 -0
  56. agno/db/redis/redis.py +1367 -0
  57. agno/db/redis/schemas.py +109 -0
  58. agno/db/redis/utils.py +288 -0
  59. agno/db/schemas/__init__.py +3 -0
  60. agno/db/schemas/evals.py +33 -0
  61. agno/db/schemas/knowledge.py +40 -0
  62. agno/db/schemas/memory.py +46 -0
  63. agno/db/singlestore/__init__.py +3 -0
  64. agno/db/singlestore/schemas.py +116 -0
  65. agno/db/singlestore/singlestore.py +1712 -0
  66. agno/db/singlestore/utils.py +326 -0
  67. agno/db/sqlite/__init__.py +3 -0
  68. agno/db/sqlite/schemas.py +119 -0
  69. agno/db/sqlite/sqlite.py +1676 -0
  70. agno/db/sqlite/utils.py +268 -0
  71. agno/db/utils.py +88 -0
  72. agno/eval/__init__.py +14 -0
  73. agno/eval/accuracy.py +154 -48
  74. agno/eval/performance.py +88 -23
  75. agno/eval/reliability.py +73 -20
  76. agno/eval/utils.py +23 -13
  77. agno/integrations/discord/__init__.py +3 -0
  78. agno/{app → integrations}/discord/client.py +10 -10
  79. agno/knowledge/__init__.py +2 -2
  80. agno/{document → knowledge}/chunking/agentic.py +2 -2
  81. agno/{document → knowledge}/chunking/document.py +2 -2
  82. agno/{document → knowledge}/chunking/fixed.py +3 -3
  83. agno/{document → knowledge}/chunking/markdown.py +2 -2
  84. agno/{document → knowledge}/chunking/recursive.py +2 -2
  85. agno/{document → knowledge}/chunking/row.py +2 -2
  86. agno/knowledge/chunking/semantic.py +59 -0
  87. agno/knowledge/chunking/strategy.py +121 -0
  88. agno/knowledge/content.py +74 -0
  89. agno/knowledge/document/__init__.py +5 -0
  90. agno/{document → knowledge/document}/base.py +12 -2
  91. agno/knowledge/embedder/__init__.py +5 -0
  92. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  93. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  94. agno/{embedder → knowledge/embedder}/base.py +6 -0
  95. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  96. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  97. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  98. agno/{embedder → knowledge/embedder}/google.py +74 -1
  99. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  100. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  101. agno/knowledge/embedder/langdb.py +22 -0
  102. agno/knowledge/embedder/mistral.py +139 -0
  103. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  104. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  105. agno/knowledge/embedder/openai.py +223 -0
  106. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  107. agno/{embedder → knowledge/embedder}/together.py +1 -1
  108. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  109. agno/knowledge/knowledge.py +1551 -0
  110. agno/knowledge/reader/__init__.py +7 -0
  111. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  112. agno/knowledge/reader/base.py +88 -0
  113. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  114. agno/knowledge/reader/docx_reader.py +83 -0
  115. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  116. agno/{document → knowledge}/reader/json_reader.py +30 -9
  117. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  118. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  119. agno/knowledge/reader/reader_factory.py +268 -0
  120. agno/knowledge/reader/s3_reader.py +101 -0
  121. agno/{document → knowledge}/reader/text_reader.py +31 -10
  122. agno/knowledge/reader/url_reader.py +128 -0
  123. agno/knowledge/reader/web_search_reader.py +366 -0
  124. agno/{document → knowledge}/reader/website_reader.py +37 -10
  125. agno/knowledge/reader/wikipedia_reader.py +59 -0
  126. agno/knowledge/reader/youtube_reader.py +78 -0
  127. agno/knowledge/remote_content/remote_content.py +88 -0
  128. agno/{reranker → knowledge/reranker}/base.py +1 -1
  129. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  130. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  131. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  132. agno/knowledge/types.py +30 -0
  133. agno/knowledge/utils.py +169 -0
  134. agno/media.py +269 -268
  135. agno/memory/__init__.py +2 -10
  136. agno/memory/manager.py +1003 -148
  137. agno/models/aimlapi/__init__.py +2 -2
  138. agno/models/aimlapi/aimlapi.py +6 -6
  139. agno/models/anthropic/claude.py +128 -72
  140. agno/models/aws/bedrock.py +107 -175
  141. agno/models/aws/claude.py +64 -18
  142. agno/models/azure/ai_foundry.py +73 -23
  143. agno/models/base.py +346 -290
  144. agno/models/cerebras/cerebras.py +84 -27
  145. agno/models/cohere/chat.py +106 -98
  146. agno/models/google/gemini.py +105 -46
  147. agno/models/groq/groq.py +97 -35
  148. agno/models/huggingface/huggingface.py +92 -27
  149. agno/models/ibm/watsonx.py +72 -13
  150. agno/models/litellm/chat.py +85 -13
  151. agno/models/message.py +46 -151
  152. agno/models/meta/llama.py +85 -49
  153. agno/models/metrics.py +120 -0
  154. agno/models/mistral/mistral.py +90 -21
  155. agno/models/ollama/__init__.py +0 -2
  156. agno/models/ollama/chat.py +85 -47
  157. agno/models/openai/chat.py +154 -37
  158. agno/models/openai/responses.py +178 -105
  159. agno/models/perplexity/perplexity.py +26 -2
  160. agno/models/portkey/portkey.py +0 -7
  161. agno/models/response.py +15 -9
  162. agno/models/utils.py +20 -0
  163. agno/models/vercel/__init__.py +2 -2
  164. agno/models/vercel/v0.py +1 -1
  165. agno/models/vllm/__init__.py +2 -2
  166. agno/models/vllm/vllm.py +3 -3
  167. agno/models/xai/xai.py +10 -10
  168. agno/os/__init__.py +3 -0
  169. agno/os/app.py +497 -0
  170. agno/os/auth.py +47 -0
  171. agno/os/config.py +103 -0
  172. agno/os/interfaces/agui/__init__.py +3 -0
  173. agno/os/interfaces/agui/agui.py +31 -0
  174. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  175. agno/{app → os/interfaces}/agui/utils.py +65 -28
  176. agno/os/interfaces/base.py +21 -0
  177. agno/os/interfaces/slack/__init__.py +3 -0
  178. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  179. agno/os/interfaces/slack/slack.py +32 -0
  180. agno/os/interfaces/whatsapp/__init__.py +3 -0
  181. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  182. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  183. agno/os/mcp.py +235 -0
  184. agno/os/router.py +1400 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +393 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +850 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +410 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +178 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +536 -0
  201. agno/os/schema.py +945 -0
  202. agno/{app/playground → os}/settings.py +7 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/agent.py +633 -0
  212. agno/run/base.py +53 -77
  213. agno/run/cancel.py +81 -0
  214. agno/run/team.py +243 -96
  215. agno/run/workflow.py +550 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +3260 -4824
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +43 -23
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +20 -17
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +22 -12
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +17 -8
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +62 -62
  252. agno/tools/eleven_labs.py +36 -29
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +30 -30
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +17 -18
  260. agno/tools/function.py +127 -18
  261. agno/tools/giphy.py +23 -11
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +32 -20
  276. agno/tools/mcp.py +1 -2
  277. agno/tools/mem0.py +18 -12
  278. agno/tools/memori.py +14 -10
  279. agno/tools/mlx_transcribe.py +3 -2
  280. agno/tools/models/azure_openai.py +33 -15
  281. agno/tools/models/gemini.py +59 -32
  282. agno/tools/models/groq.py +30 -23
  283. agno/tools/models/nebius.py +28 -12
  284. agno/tools/models_labs.py +40 -16
  285. agno/tools/moviepy_video.py +7 -6
  286. agno/tools/neo4j.py +10 -8
  287. agno/tools/newspaper.py +7 -2
  288. agno/tools/newspaper4k.py +8 -3
  289. agno/tools/openai.py +58 -32
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +63 -47
  292. agno/tools/openweather.py +14 -12
  293. agno/tools/pandas.py +11 -3
  294. agno/tools/postgres.py +4 -12
  295. agno/tools/pubmed.py +4 -1
  296. agno/tools/python.py +9 -22
  297. agno/tools/reasoning.py +35 -27
  298. agno/tools/reddit.py +11 -26
  299. agno/tools/replicate.py +55 -42
  300. agno/tools/resend.py +4 -1
  301. agno/tools/scrapegraph.py +15 -14
  302. agno/tools/searxng.py +10 -23
  303. agno/tools/serpapi.py +6 -3
  304. agno/tools/serper.py +13 -4
  305. agno/tools/shell.py +9 -2
  306. agno/tools/slack.py +12 -11
  307. agno/tools/sleep.py +3 -2
  308. agno/tools/spider.py +24 -4
  309. agno/tools/sql.py +7 -6
  310. agno/tools/tavily.py +6 -4
  311. agno/tools/telegram.py +12 -4
  312. agno/tools/todoist.py +11 -31
  313. agno/tools/toolkit.py +1 -1
  314. agno/tools/trafilatura.py +22 -6
  315. agno/tools/trello.py +9 -22
  316. agno/tools/twilio.py +10 -3
  317. agno/tools/user_control_flow.py +6 -1
  318. agno/tools/valyu.py +34 -5
  319. agno/tools/visualization.py +19 -28
  320. agno/tools/webbrowser.py +4 -3
  321. agno/tools/webex.py +11 -7
  322. agno/tools/website.py +15 -46
  323. agno/tools/webtools.py +12 -4
  324. agno/tools/whatsapp.py +5 -9
  325. agno/tools/wikipedia.py +20 -13
  326. agno/tools/x.py +14 -13
  327. agno/tools/yfinance.py +13 -40
  328. agno/tools/youtube.py +26 -20
  329. agno/tools/zendesk.py +7 -2
  330. agno/tools/zep.py +10 -7
  331. agno/tools/zoom.py +10 -9
  332. agno/utils/common.py +1 -19
  333. agno/utils/events.py +100 -123
  334. agno/utils/gemini.py +1 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +54 -4
  337. agno/utils/mcp.py +68 -10
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/aws_claude.py +1 -1
  341. agno/utils/models/claude.py +6 -12
  342. agno/utils/models/cohere.py +1 -1
  343. agno/utils/models/mistral.py +8 -7
  344. agno/utils/models/schema_utils.py +3 -3
  345. agno/utils/models/watsonx.py +1 -1
  346. agno/utils/openai.py +1 -1
  347. agno/utils/pprint.py +33 -32
  348. agno/utils/print_response/agent.py +779 -0
  349. agno/utils/print_response/team.py +1669 -0
  350. agno/utils/print_response/workflow.py +1451 -0
  351. agno/utils/prompts.py +14 -14
  352. agno/utils/reasoning.py +87 -0
  353. agno/utils/response.py +42 -42
  354. agno/utils/streamlit.py +481 -0
  355. agno/utils/string.py +8 -22
  356. agno/utils/team.py +50 -0
  357. agno/utils/timer.py +2 -2
  358. agno/vectordb/base.py +33 -21
  359. agno/vectordb/cassandra/cassandra.py +287 -23
  360. agno/vectordb/chroma/chromadb.py +482 -59
  361. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  362. agno/vectordb/couchbase/couchbase.py +309 -29
  363. agno/vectordb/lancedb/lance_db.py +360 -21
  364. agno/vectordb/langchaindb/__init__.py +5 -0
  365. agno/vectordb/langchaindb/langchaindb.py +145 -0
  366. agno/vectordb/lightrag/__init__.py +5 -0
  367. agno/vectordb/lightrag/lightrag.py +374 -0
  368. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  369. agno/vectordb/milvus/milvus.py +242 -32
  370. agno/vectordb/mongodb/mongodb.py +200 -24
  371. agno/vectordb/pgvector/pgvector.py +319 -37
  372. agno/vectordb/pineconedb/pineconedb.py +221 -27
  373. agno/vectordb/qdrant/qdrant.py +334 -14
  374. agno/vectordb/singlestore/singlestore.py +286 -29
  375. agno/vectordb/surrealdb/surrealdb.py +187 -7
  376. agno/vectordb/upstashdb/upstashdb.py +342 -26
  377. agno/vectordb/weaviate/weaviate.py +227 -165
  378. agno/workflow/__init__.py +17 -13
  379. agno/workflow/{v2/condition.py → condition.py} +135 -32
  380. agno/workflow/{v2/loop.py → loop.py} +115 -28
  381. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  382. agno/workflow/{v2/router.py → router.py} +133 -32
  383. agno/workflow/{v2/step.py → step.py} +207 -49
  384. agno/workflow/{v2/steps.py → steps.py} +147 -66
  385. agno/workflow/types.py +482 -0
  386. agno/workflow/workflow.py +2410 -696
  387. agno-2.0.0.dist-info/METADATA +494 -0
  388. agno-2.0.0.dist-info/RECORD +515 -0
  389. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  390. agno/agent/metrics.py +0 -110
  391. agno/api/app.py +0 -35
  392. agno/api/playground.py +0 -92
  393. agno/api/schemas/app.py +0 -12
  394. agno/api/schemas/playground.py +0 -22
  395. agno/api/schemas/user.py +0 -35
  396. agno/api/schemas/workspace.py +0 -46
  397. agno/api/user.py +0 -160
  398. agno/api/workflows.py +0 -33
  399. agno/api/workspace.py +0 -175
  400. agno/app/agui/__init__.py +0 -3
  401. agno/app/agui/app.py +0 -17
  402. agno/app/agui/sync_router.py +0 -120
  403. agno/app/base.py +0 -186
  404. agno/app/discord/__init__.py +0 -3
  405. agno/app/fastapi/__init__.py +0 -3
  406. agno/app/fastapi/app.py +0 -107
  407. agno/app/fastapi/async_router.py +0 -457
  408. agno/app/fastapi/sync_router.py +0 -448
  409. agno/app/playground/app.py +0 -228
  410. agno/app/playground/async_router.py +0 -1053
  411. agno/app/playground/deploy.py +0 -249
  412. agno/app/playground/operator.py +0 -183
  413. agno/app/playground/schemas.py +0 -223
  414. agno/app/playground/serve.py +0 -55
  415. agno/app/playground/sync_router.py +0 -1045
  416. agno/app/playground/utils.py +0 -46
  417. agno/app/settings.py +0 -15
  418. agno/app/slack/__init__.py +0 -3
  419. agno/app/slack/app.py +0 -19
  420. agno/app/slack/sync_router.py +0 -92
  421. agno/app/utils.py +0 -54
  422. agno/app/whatsapp/__init__.py +0 -3
  423. agno/app/whatsapp/app.py +0 -15
  424. agno/app/whatsapp/sync_router.py +0 -197
  425. agno/cli/auth_server.py +0 -249
  426. agno/cli/config.py +0 -274
  427. agno/cli/console.py +0 -88
  428. agno/cli/credentials.py +0 -23
  429. agno/cli/entrypoint.py +0 -571
  430. agno/cli/operator.py +0 -357
  431. agno/cli/settings.py +0 -96
  432. agno/cli/ws/ws_cli.py +0 -817
  433. agno/constants.py +0 -13
  434. agno/document/__init__.py +0 -5
  435. agno/document/chunking/semantic.py +0 -45
  436. agno/document/chunking/strategy.py +0 -31
  437. agno/document/reader/__init__.py +0 -5
  438. agno/document/reader/base.py +0 -47
  439. agno/document/reader/docx_reader.py +0 -60
  440. agno/document/reader/gcs/pdf_reader.py +0 -44
  441. agno/document/reader/s3/pdf_reader.py +0 -59
  442. agno/document/reader/s3/text_reader.py +0 -63
  443. agno/document/reader/url_reader.py +0 -59
  444. agno/document/reader/youtube_reader.py +0 -58
  445. agno/embedder/__init__.py +0 -5
  446. agno/embedder/langdb.py +0 -80
  447. agno/embedder/mistral.py +0 -82
  448. agno/embedder/openai.py +0 -78
  449. agno/file/__init__.py +0 -5
  450. agno/file/file.py +0 -16
  451. agno/file/local/csv.py +0 -32
  452. agno/file/local/txt.py +0 -19
  453. agno/infra/app.py +0 -240
  454. agno/infra/base.py +0 -144
  455. agno/infra/context.py +0 -20
  456. agno/infra/db_app.py +0 -52
  457. agno/infra/resource.py +0 -205
  458. agno/infra/resources.py +0 -55
  459. agno/knowledge/agent.py +0 -702
  460. agno/knowledge/arxiv.py +0 -33
  461. agno/knowledge/combined.py +0 -36
  462. agno/knowledge/csv.py +0 -144
  463. agno/knowledge/csv_url.py +0 -124
  464. agno/knowledge/document.py +0 -223
  465. agno/knowledge/docx.py +0 -137
  466. agno/knowledge/firecrawl.py +0 -34
  467. agno/knowledge/gcs/__init__.py +0 -0
  468. agno/knowledge/gcs/base.py +0 -39
  469. agno/knowledge/gcs/pdf.py +0 -125
  470. agno/knowledge/json.py +0 -137
  471. agno/knowledge/langchain.py +0 -71
  472. agno/knowledge/light_rag.py +0 -273
  473. agno/knowledge/llamaindex.py +0 -66
  474. agno/knowledge/markdown.py +0 -154
  475. agno/knowledge/pdf.py +0 -164
  476. agno/knowledge/pdf_bytes.py +0 -42
  477. agno/knowledge/pdf_url.py +0 -148
  478. agno/knowledge/s3/__init__.py +0 -0
  479. agno/knowledge/s3/base.py +0 -64
  480. agno/knowledge/s3/pdf.py +0 -33
  481. agno/knowledge/s3/text.py +0 -34
  482. agno/knowledge/text.py +0 -141
  483. agno/knowledge/url.py +0 -46
  484. agno/knowledge/website.py +0 -179
  485. agno/knowledge/wikipedia.py +0 -32
  486. agno/knowledge/youtube.py +0 -35
  487. agno/memory/agent.py +0 -423
  488. agno/memory/classifier.py +0 -104
  489. agno/memory/db/__init__.py +0 -5
  490. agno/memory/db/base.py +0 -42
  491. agno/memory/db/mongodb.py +0 -189
  492. agno/memory/db/postgres.py +0 -203
  493. agno/memory/db/sqlite.py +0 -193
  494. agno/memory/memory.py +0 -22
  495. agno/memory/row.py +0 -36
  496. agno/memory/summarizer.py +0 -201
  497. agno/memory/summary.py +0 -19
  498. agno/memory/team.py +0 -415
  499. agno/memory/v2/__init__.py +0 -2
  500. agno/memory/v2/db/__init__.py +0 -1
  501. agno/memory/v2/db/base.py +0 -42
  502. agno/memory/v2/db/firestore.py +0 -339
  503. agno/memory/v2/db/mongodb.py +0 -196
  504. agno/memory/v2/db/postgres.py +0 -214
  505. agno/memory/v2/db/redis.py +0 -187
  506. agno/memory/v2/db/schema.py +0 -54
  507. agno/memory/v2/db/sqlite.py +0 -209
  508. agno/memory/v2/manager.py +0 -437
  509. agno/memory/v2/memory.py +0 -1097
  510. agno/memory/v2/schema.py +0 -55
  511. agno/memory/v2/summarizer.py +0 -215
  512. agno/memory/workflow.py +0 -38
  513. agno/models/ollama/tools.py +0 -430
  514. agno/models/qwen/__init__.py +0 -5
  515. agno/playground/__init__.py +0 -10
  516. agno/playground/deploy.py +0 -3
  517. agno/playground/playground.py +0 -3
  518. agno/playground/serve.py +0 -3
  519. agno/playground/settings.py +0 -3
  520. agno/reranker/__init__.py +0 -0
  521. agno/run/response.py +0 -467
  522. agno/run/v2/__init__.py +0 -0
  523. agno/run/v2/workflow.py +0 -567
  524. agno/storage/__init__.py +0 -0
  525. agno/storage/agent/__init__.py +0 -0
  526. agno/storage/agent/dynamodb.py +0 -1
  527. agno/storage/agent/json.py +0 -1
  528. agno/storage/agent/mongodb.py +0 -1
  529. agno/storage/agent/postgres.py +0 -1
  530. agno/storage/agent/singlestore.py +0 -1
  531. agno/storage/agent/sqlite.py +0 -1
  532. agno/storage/agent/yaml.py +0 -1
  533. agno/storage/base.py +0 -60
  534. agno/storage/dynamodb.py +0 -673
  535. agno/storage/firestore.py +0 -297
  536. agno/storage/gcs_json.py +0 -261
  537. agno/storage/in_memory.py +0 -234
  538. agno/storage/json.py +0 -237
  539. agno/storage/mongodb.py +0 -328
  540. agno/storage/mysql.py +0 -685
  541. agno/storage/postgres.py +0 -682
  542. agno/storage/redis.py +0 -336
  543. agno/storage/session/__init__.py +0 -16
  544. agno/storage/session/agent.py +0 -64
  545. agno/storage/session/team.py +0 -63
  546. agno/storage/session/v2/__init__.py +0 -5
  547. agno/storage/session/workflow.py +0 -61
  548. agno/storage/singlestore.py +0 -606
  549. agno/storage/sqlite.py +0 -646
  550. agno/storage/workflow/__init__.py +0 -0
  551. agno/storage/workflow/mongodb.py +0 -1
  552. agno/storage/workflow/postgres.py +0 -1
  553. agno/storage/workflow/sqlite.py +0 -1
  554. agno/storage/yaml.py +0 -241
  555. agno/tools/thinking.py +0 -73
  556. agno/utils/defaults.py +0 -57
  557. agno/utils/filesystem.py +0 -39
  558. agno/utils/git.py +0 -52
  559. agno/utils/json_io.py +0 -30
  560. agno/utils/load_env.py +0 -19
  561. agno/utils/py_io.py +0 -19
  562. agno/utils/pyproject.py +0 -18
  563. agno/utils/resource_filter.py +0 -31
  564. agno/workflow/v2/__init__.py +0 -21
  565. agno/workflow/v2/types.py +0 -357
  566. agno/workflow/v2/workflow.py +0 -3313
  567. agno/workspace/__init__.py +0 -0
  568. agno/workspace/config.py +0 -325
  569. agno/workspace/enums.py +0 -6
  570. agno/workspace/helpers.py +0 -52
  571. agno/workspace/operator.py +0 -757
  572. agno/workspace/settings.py +0 -158
  573. agno-1.8.2.dist-info/METADATA +0 -982
  574. agno-1.8.2.dist-info/RECORD +0 -566
  575. agno-1.8.2.dist-info/entry_points.txt +0 -3
  576. agno-1.8.2.dist-info/licenses/LICENSE +0 -375
  577. /agno/{app → db/migrations}/__init__.py +0 -0
  578. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  579. /agno/{cli → integrations}/__init__.py +0 -0
  580. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  581. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  582. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  583. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  584. /agno/{app → os/interfaces}/slack/security.py +0 -0
  585. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  586. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  587. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  588. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  589. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/os/config.py ADDED
@@ -0,0 +1,103 @@
1
+ """Schemas related to the AgentOS configuration"""
2
+
3
+ from typing import Generic, List, Optional, TypeVar
4
+
5
+ from pydantic import BaseModel, field_validator
6
+
7
+
8
+ class EvalsDomainConfig(BaseModel):
9
+ """Configuration for the Evals domain of the AgentOS"""
10
+
11
+ display_name: Optional[str] = None
12
+ available_models: Optional[List[str]] = None
13
+
14
+
15
+ class SessionDomainConfig(BaseModel):
16
+ """Configuration for the Session domain of the AgentOS"""
17
+
18
+ display_name: Optional[str] = None
19
+
20
+
21
+ class KnowledgeDomainConfig(BaseModel):
22
+ """Configuration for the Knowledge domain of the AgentOS"""
23
+
24
+ display_name: Optional[str] = None
25
+
26
+
27
+ class MetricsDomainConfig(BaseModel):
28
+ """Configuration for the Metrics domain of the AgentOS"""
29
+
30
+ display_name: Optional[str] = None
31
+
32
+
33
+ class MemoryDomainConfig(BaseModel):
34
+ """Configuration for the Memory domain of the AgentOS"""
35
+
36
+ display_name: Optional[str] = None
37
+
38
+
39
+ DomainConfigType = TypeVar("DomainConfigType")
40
+
41
+
42
+ class DatabaseConfig(BaseModel, Generic[DomainConfigType]):
43
+ """Configuration for a domain when used with the contextual database"""
44
+
45
+ db_id: str
46
+ domain_config: Optional[DomainConfigType] = None
47
+
48
+
49
+ class EvalsConfig(EvalsDomainConfig):
50
+ """Configuration for the Evals domain of the AgentOS"""
51
+
52
+ dbs: Optional[List[DatabaseConfig[EvalsDomainConfig]]] = None
53
+
54
+
55
+ class SessionConfig(SessionDomainConfig):
56
+ """Configuration for the Session domain of the AgentOS"""
57
+
58
+ dbs: Optional[List[DatabaseConfig[SessionDomainConfig]]] = None
59
+
60
+
61
+ class MemoryConfig(MemoryDomainConfig):
62
+ """Configuration for the Memory domain of the AgentOS"""
63
+
64
+ dbs: Optional[List[DatabaseConfig[MemoryDomainConfig]]] = None
65
+
66
+
67
+ class KnowledgeConfig(KnowledgeDomainConfig):
68
+ """Configuration for the Knowledge domain of the AgentOS"""
69
+
70
+ dbs: Optional[List[DatabaseConfig[KnowledgeDomainConfig]]] = None
71
+
72
+
73
+ class MetricsConfig(MetricsDomainConfig):
74
+ """Configuration for the Metrics domain of the AgentOS"""
75
+
76
+ dbs: Optional[List[DatabaseConfig[MetricsDomainConfig]]] = None
77
+
78
+
79
+ class ChatConfig(BaseModel):
80
+ """Configuration for the Chat page of the AgentOS"""
81
+
82
+ quick_prompts: dict[str, list[str]]
83
+
84
+ # Limit the number of quick prompts to 3 (per agent/team/workflow)
85
+ @field_validator("quick_prompts")
86
+ @classmethod
87
+ def limit_lists(cls, v):
88
+ for key, lst in v.items():
89
+ if len(lst) > 3:
90
+ raise ValueError(f"Too many quick prompts for '{key}', maximum allowed is 3")
91
+ return v
92
+
93
+
94
+ class AgentOSConfig(BaseModel):
95
+ """General configuration for an AgentOS instance"""
96
+
97
+ available_models: Optional[List[str]] = None
98
+ chat: Optional[ChatConfig] = None
99
+ evals: Optional[EvalsConfig] = None
100
+ knowledge: Optional[KnowledgeConfig] = None
101
+ memory: Optional[MemoryConfig] = None
102
+ session: Optional[SessionConfig] = None
103
+ metrics: Optional[MetricsConfig] = None
@@ -0,0 +1,3 @@
1
+ from agno.os.interfaces.agui.agui import AGUI
2
+
3
+ __all__ = ["AGUI"]
@@ -0,0 +1,31 @@
1
+ """Main class for the AG-UI app, used to expose an Agno Agent or Team in an AG-UI compatible format."""
2
+
3
+ from typing import Optional
4
+
5
+ from fastapi.routing import APIRouter
6
+
7
+ from agno.agent import Agent
8
+ from agno.os.interfaces.agui.router import attach_routes
9
+ from agno.os.interfaces.base import BaseInterface
10
+ from agno.team import Team
11
+
12
+
13
+ class AGUI(BaseInterface):
14
+ type = "agui"
15
+
16
+ router: APIRouter
17
+
18
+ def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
19
+ self.agent = agent
20
+ self.team = team
21
+
22
+ if not self.agent and not self.team:
23
+ raise ValueError("AGUI requires an agent and a team")
24
+
25
+ def get_router(self, **kwargs) -> APIRouter:
26
+ # Cannot be overridden
27
+ self.router = APIRouter(tags=["AGUI"])
28
+
29
+ self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
30
+
31
+ return self.router
@@ -16,7 +16,10 @@ from fastapi import APIRouter
16
16
  from fastapi.responses import StreamingResponse
17
17
 
18
18
  from agno.agent.agent import Agent
19
- from agno.app.agui.utils import async_stream_agno_response_as_agui_events, convert_agui_messages_to_agno_messages
19
+ from agno.os.interfaces.agui.utils import (
20
+ async_stream_agno_response_as_agui_events,
21
+ convert_agui_messages_to_agno_messages,
22
+ )
20
23
  from agno.team.team import Team
21
24
 
22
25
  logger = logging.getLogger(__name__)
@@ -32,8 +35,8 @@ async def run_agent(agent: Agent, run_input: RunAgentInput) -> AsyncIterator[Bas
32
35
  yield RunStartedEvent(type=EventType.RUN_STARTED, thread_id=run_input.thread_id, run_id=run_id)
33
36
 
34
37
  # Request streaming response from agent
35
- response_stream = await agent.arun(
36
- messages=messages,
38
+ response_stream = agent.arun(
39
+ input=messages,
37
40
  session_id=run_input.thread_id,
38
41
  stream=True,
39
42
  stream_intermediate_steps=True,
@@ -41,7 +44,9 @@ async def run_agent(agent: Agent, run_input: RunAgentInput) -> AsyncIterator[Bas
41
44
 
42
45
  # Stream the response content in AG-UI format
43
46
  async for event in async_stream_agno_response_as_agui_events(
44
- response_stream=response_stream, thread_id=run_input.thread_id, run_id=run_id
47
+ response_stream=response_stream, # type: ignore
48
+ thread_id=run_input.thread_id,
49
+ run_id=run_id,
45
50
  ):
46
51
  yield event
47
52
 
@@ -60,8 +65,8 @@ async def run_team(team: Team, input: RunAgentInput) -> AsyncIterator[BaseEvent]
60
65
  yield RunStartedEvent(type=EventType.RUN_STARTED, thread_id=input.thread_id, run_id=run_id)
61
66
 
62
67
  # Request streaming response from team
63
- response_stream = await team.arun(
64
- message=messages,
68
+ response_stream = team.arun(
69
+ input=messages,
65
70
  session_id=input.thread_id,
66
71
  stream=True,
67
72
  stream_intermediate_steps=True,
@@ -78,15 +83,14 @@ async def run_team(team: Team, input: RunAgentInput) -> AsyncIterator[BaseEvent]
78
83
  yield RunErrorEvent(type=EventType.RUN_ERROR, message=str(e))
79
84
 
80
85
 
81
- def get_async_agui_router(agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
82
- """Return an AG-UI compatible FastAPI router."""
83
- if (agent is None and team is None) or (agent is not None and team is not None):
84
- raise ValueError("One of 'agent' or 'team' must be provided.")
86
+ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
87
+ if agent is None and team is None:
88
+ raise ValueError("Either agent or team must be provided.")
85
89
 
86
- router = APIRouter()
87
90
  encoder = EventEncoder()
88
91
 
89
- async def _run(run_input: RunAgentInput):
92
+ @router.post("/agui")
93
+ async def run_agent_agui(run_input: RunAgentInput):
90
94
  async def event_generator():
91
95
  if agent:
92
96
  async for event in run_agent(agent, run_input):
@@ -109,10 +113,6 @@ def get_async_agui_router(agent: Optional[Agent] = None, team: Optional[Team] =
109
113
  },
110
114
  )
111
115
 
112
- @router.post("/agui")
113
- async def run_agent_agui(run_input: RunAgentInput):
114
- return await _run(run_input)
115
-
116
116
  @router.get("/status")
117
117
  async def get_status():
118
118
  return {"status": "available"}
@@ -24,9 +24,9 @@ from ag_ui.core import (
24
24
  from ag_ui.core.types import Message as AGUIMessage
25
25
 
26
26
  from agno.models.message import Message
27
- from agno.run.response import RunEvent, RunResponseContentEvent, RunResponseEvent, RunResponsePausedEvent
28
- from agno.run.team import RunResponseContentEvent as TeamRunResponseContentEvent
29
- from agno.run.team import TeamRunEvent, TeamRunResponseEvent
27
+ from agno.run.agent import RunContentEvent, RunEvent, RunOutputEvent, RunPausedEvent
28
+ from agno.run.team import RunContentEvent as TeamRunContentEvent
29
+ from agno.run.team import TeamRunEvent, TeamRunOutputEvent
30
30
  from agno.utils.message import get_text_from_message
31
31
 
32
32
 
@@ -90,18 +90,18 @@ def convert_agui_messages_to_agno_messages(messages: List[AGUIMessage]) -> List[
90
90
  return result
91
91
 
92
92
 
93
- def extract_team_response_chunk_content(response: TeamRunResponseContentEvent) -> str:
93
+ def extract_team_response_chunk_content(response: TeamRunContentEvent) -> str:
94
94
  """Given a response stream chunk, find and extract the content."""
95
95
 
96
96
  # Handle Team members' responses
97
97
  members_content = []
98
98
  if hasattr(response, "member_responses") and response.member_responses: # type: ignore
99
99
  for member_resp in response.member_responses: # type: ignore
100
- if isinstance(member_resp, RunResponseContentEvent):
100
+ if isinstance(member_resp, RunContentEvent):
101
101
  member_content = extract_response_chunk_content(member_resp)
102
102
  if member_content:
103
103
  members_content.append(f"Team member: {member_content}")
104
- elif isinstance(member_resp, TeamRunResponseContentEvent):
104
+ elif isinstance(member_resp, TeamRunContentEvent):
105
105
  member_content = extract_team_response_chunk_content(member_resp)
106
106
  if member_content:
107
107
  members_content.append(f"Team member: {member_content}")
@@ -113,7 +113,7 @@ def extract_team_response_chunk_content(response: TeamRunResponseContentEvent) -
113
113
  return main_content + members_response
114
114
 
115
115
 
116
- def extract_response_chunk_content(response: RunResponseContentEvent) -> str:
116
+ def extract_response_chunk_content(response: RunContentEvent) -> str:
117
117
  """Given a response stream chunk, find and extract the content."""
118
118
 
119
119
  if hasattr(response, "messages") and response.messages: # type: ignore
@@ -127,7 +127,7 @@ def extract_response_chunk_content(response: RunResponseContentEvent) -> str:
127
127
 
128
128
 
129
129
  def _create_events_from_chunk(
130
- chunk: Union[RunResponseEvent, TeamRunResponseEvent],
130
+ chunk: Union[RunOutputEvent, TeamRunOutputEvent],
131
131
  message_id: str,
132
132
  message_started: bool,
133
133
  event_buffer: EventBuffer,
@@ -139,9 +139,9 @@ def _create_events_from_chunk(
139
139
  events_to_emit: List[BaseEvent] = []
140
140
 
141
141
  # Extract content if the contextual event is a content event
142
- if chunk.event == RunEvent.run_response_content:
142
+ if chunk.event == RunEvent.run_content:
143
143
  content = extract_response_chunk_content(chunk) # type: ignore
144
- elif chunk.event == TeamRunEvent.run_response_content:
144
+ elif chunk.event == TeamRunEvent.run_content:
145
145
  content = extract_team_response_chunk_content(chunk) # type: ignore
146
146
  else:
147
147
  content = None
@@ -165,7 +165,7 @@ def _create_events_from_chunk(
165
165
  message_id=message_id,
166
166
  delta=content,
167
167
  )
168
- events_to_emit.append(content_event)
168
+ events_to_emit.append(content_event) # type: ignore
169
169
 
170
170
  # Handle starting a new tool call
171
171
  elif chunk.event == RunEvent.tool_call_started:
@@ -184,7 +184,7 @@ def _create_events_from_chunk(
184
184
  tool_call_id=tool_call.tool_call_id, # type: ignore
185
185
  delta=json.dumps(tool_call.tool_args),
186
186
  )
187
- events_to_emit.append(args_event)
187
+ events_to_emit.append(args_event) # type: ignore
188
188
 
189
189
  # Handle tool call completion
190
190
  elif chunk.event == RunEvent.tool_call_completed:
@@ -195,7 +195,7 @@ def _create_events_from_chunk(
195
195
  type=EventType.TOOL_CALL_END,
196
196
  tool_call_id=tool_call.tool_call_id, # type: ignore
197
197
  )
198
- events_to_emit.append(end_event)
198
+ events_to_emit.append(end_event) # type: ignore
199
199
 
200
200
  if tool_call.result is not None:
201
201
  result_event = ToolCallResultEvent(
@@ -205,21 +205,31 @@ def _create_events_from_chunk(
205
205
  role="tool",
206
206
  message_id=str(uuid.uuid4()),
207
207
  )
208
- events_to_emit.append(result_event)
208
+ events_to_emit.append(result_event) # type: ignore
209
+
210
+ if tool_call.result is not None:
211
+ result_event = ToolCallResultEvent(
212
+ type=EventType.TOOL_CALL_RESULT,
213
+ tool_call_id=tool_call.tool_call_id, # type: ignore
214
+ content=str(tool_call.result),
215
+ role="tool",
216
+ message_id=str(uuid.uuid4()),
217
+ )
218
+ events_to_emit.append(result_event) # type: ignore
209
219
 
210
220
  # Handle reasoning
211
221
  elif chunk.event == RunEvent.reasoning_started:
212
- step_started_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning")
213
- events_to_emit.append(step_started_event)
222
+ step_started_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning") # type: ignore
223
+ events_to_emit.append(step_started_event) # type: ignore
214
224
  elif chunk.event == RunEvent.reasoning_completed:
215
- step_finished_event = StepFinishedEvent(type=EventType.STEP_FINISHED, step_name="reasoning")
216
- events_to_emit.append(step_finished_event)
225
+ step_started_event = StepFinishedEvent(type=EventType.STEP_FINISHED, step_name="reasoning") # type: ignore
226
+ events_to_emit.append(step_started_event) # type: ignore
217
227
 
218
- return events_to_emit, message_started
228
+ return events_to_emit, message_started # type: ignore
219
229
 
220
230
 
221
231
  def _create_completion_events(
222
- chunk: Union[RunResponseEvent, TeamRunResponseEvent],
232
+ chunk: Union[RunOutputEvent, TeamRunOutputEvent],
223
233
  event_buffer: EventBuffer,
224
234
  message_started: bool,
225
235
  message_id: str,
@@ -241,10 +251,10 @@ def _create_completion_events(
241
251
  # End the message and run, denoting the end of the session
242
252
  if message_started:
243
253
  end_message_event = TextMessageEndEvent(type=EventType.TEXT_MESSAGE_END, message_id=message_id)
244
- events_to_emit.append(end_message_event)
254
+ events_to_emit.append(end_message_event) # type: ignore
245
255
 
246
256
  # emit frontend tool calls, i.e. external_execution=True
247
- if isinstance(chunk, RunResponsePausedEvent) and chunk.tools is not None:
257
+ if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
248
258
  for tool in chunk.tools:
249
259
  if tool.tool_call_id is None or tool.tool_name is None:
250
260
  continue
@@ -255,14 +265,14 @@ def _create_completion_events(
255
265
  tool_call_name=tool.tool_name,
256
266
  parent_message_id=message_id,
257
267
  )
258
- events_to_emit.append(start_event)
268
+ events_to_emit.append(start_event) # type: ignore
259
269
 
260
270
  args_event = ToolCallArgsEvent(
261
271
  type=EventType.TOOL_CALL_ARGS,
262
272
  tool_call_id=tool.tool_call_id,
263
273
  delta=json.dumps(tool.tool_args),
264
274
  )
265
- events_to_emit.append(args_event)
275
+ events_to_emit.append(args_event) # type: ignore
266
276
 
267
277
  end_event = ToolCallEndEvent(
268
278
  type=EventType.TOOL_CALL_END,
@@ -270,10 +280,37 @@ def _create_completion_events(
270
280
  )
271
281
  events_to_emit.append(end_event)
272
282
 
283
+ # emit frontend tool calls, i.e. external_execution=True
284
+ if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
285
+ for tool in chunk.tools:
286
+ if tool.tool_call_id is None or tool.tool_name is None:
287
+ continue
288
+
289
+ start_event = ToolCallStartEvent(
290
+ type=EventType.TOOL_CALL_START,
291
+ tool_call_id=tool.tool_call_id,
292
+ tool_call_name=tool.tool_name,
293
+ parent_message_id=message_id,
294
+ )
295
+ events_to_emit.append(start_event) # type: ignore
296
+
297
+ args_event = ToolCallArgsEvent(
298
+ type=EventType.TOOL_CALL_ARGS,
299
+ tool_call_id=tool.tool_call_id,
300
+ delta=json.dumps(tool.tool_args),
301
+ )
302
+ events_to_emit.append(args_event) # type: ignore
303
+
304
+ end_event = ToolCallEndEvent(
305
+ type=EventType.TOOL_CALL_END,
306
+ tool_call_id=tool.tool_call_id,
307
+ )
308
+ events_to_emit.append(end_event) # type: ignore
309
+
273
310
  run_finished_event = RunFinishedEvent(type=EventType.RUN_FINISHED, thread_id=thread_id, run_id=run_id)
274
- events_to_emit.append(run_finished_event)
311
+ events_to_emit.append(run_finished_event) # type: ignore
275
312
 
276
- return events_to_emit
313
+ return events_to_emit # type: ignore
277
314
 
278
315
 
279
316
  def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseEvent]:
@@ -327,7 +364,7 @@ def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseE
327
364
 
328
365
 
329
366
  def stream_agno_response_as_agui_events(
330
- response_stream: Iterator[Union[RunResponseEvent, TeamRunResponseEvent]], thread_id: str, run_id: str
367
+ response_stream: Iterator[Union[RunOutputEvent, TeamRunOutputEvent]], thread_id: str, run_id: str
331
368
  ) -> Iterator[BaseEvent]:
332
369
  """Map the Agno response stream to AG-UI format, handling event ordering constraints."""
333
370
  message_id = str(uuid.uuid4())
@@ -362,7 +399,7 @@ def stream_agno_response_as_agui_events(
362
399
 
363
400
  # Async version - thin wrapper
364
401
  async def async_stream_agno_response_as_agui_events(
365
- response_stream: AsyncIterator[Union[RunResponseEvent, TeamRunResponseEvent]],
402
+ response_stream: AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]],
366
403
  thread_id: str,
367
404
  run_id: str,
368
405
  ) -> AsyncIterator[BaseEvent]:
@@ -0,0 +1,21 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional
3
+
4
+ from fastapi import APIRouter
5
+
6
+ from agno.agent import Agent
7
+ from agno.team import Team
8
+
9
+
10
+ class BaseInterface(ABC):
11
+ type: str
12
+ version: str = "1.0"
13
+ router_prefix: str = ""
14
+ agent: Optional[Agent] = None
15
+ team: Optional[Team] = None
16
+
17
+ router: APIRouter
18
+
19
+ @abstractmethod
20
+ def get_router(self, use_async: bool = True, **kwargs) -> APIRouter:
21
+ pass
@@ -0,0 +1,3 @@
1
+ from agno.os.interfaces.slack.slack import Slack
2
+
3
+ __all__ = ["Slack"]
@@ -3,15 +3,13 @@ from typing import Optional
3
3
  from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
4
4
 
5
5
  from agno.agent.agent import Agent
6
- from agno.app.slack.security import verify_slack_signature
6
+ from agno.os.interfaces.slack.security import verify_slack_signature
7
7
  from agno.team.team import Team
8
8
  from agno.tools.slack import SlackTools
9
9
  from agno.utils.log import log_info
10
10
 
11
11
 
12
- def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
13
- router = APIRouter()
14
-
12
+ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
15
13
  @router.post("/slack/events")
16
14
  async def slack_events(request: Request, background_tasks: BackgroundTasks):
17
15
  body = await request.body()
@@ -44,7 +42,7 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
44
42
  async def _process_slack_event(event: dict):
45
43
  if event.get("type") == "message":
46
44
  user = None
47
- message_text = event.get("text")
45
+ message_text = event.get("text", "")
48
46
  channel_id = event.get("channel", "")
49
47
  user = event.get("user")
50
48
  if event.get("thread_ts"):
@@ -0,0 +1,32 @@
1
+ import logging
2
+ from typing import Optional
3
+
4
+ from fastapi.routing import APIRouter
5
+
6
+ from agno.agent.agent import Agent
7
+ from agno.os.interfaces.base import BaseInterface
8
+ from agno.os.interfaces.slack.router import attach_routes
9
+ from agno.team.team import Team
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class Slack(BaseInterface):
15
+ type = "slack"
16
+
17
+ router: APIRouter
18
+
19
+ def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
20
+ self.agent = agent
21
+ self.team = team
22
+
23
+ if not self.agent and not self.team:
24
+ raise ValueError("Slack requires an agent and a team")
25
+
26
+ def get_router(self, **kwargs) -> APIRouter:
27
+ # Cannot be overridden
28
+ self.router = APIRouter(prefix="/slack", tags=["Slack"])
29
+
30
+ self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
31
+
32
+ return self.router
@@ -0,0 +1,3 @@
1
+ from agno.os.interfaces.whatsapp.whatsapp import Whatsapp
2
+
3
+ __all__ = ["Whatsapp"]
@@ -15,9 +15,7 @@ from agno.utils.whatsapp import get_media_async, send_image_message_async, typin
15
15
  from .security import validate_webhook_signature
16
16
 
17
17
 
18
- def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
19
- router = APIRouter()
20
-
18
+ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
21
19
  if agent is None and team is None:
22
20
  raise ValueError("Either agent or team must be provided.")
23
21
 
@@ -128,7 +126,7 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
128
126
  audio=[Audio(content=await get_media_async(message_audio))] if message_audio else None,
129
127
  )
130
128
  elif team:
131
- response = await team.arun(
129
+ response = await team.arun( # type: ignore
132
130
  message_text,
133
131
  user_id=phone_number,
134
132
  files=[File(content=await get_media_async(message_doc))] if message_doc else None,
@@ -167,9 +165,8 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
167
165
  log_warning(
168
166
  f"Could not process image content for user {phone_number}. Type: {type(image_content)}"
169
167
  )
170
- await _send_whatsapp_message(phone_number, response.content) # Send text part if image fails
171
- else:
172
- await _send_whatsapp_message(phone_number, response.content)
168
+ await _send_whatsapp_message(phone_number, response.content) # type: ignore
169
+ await _send_whatsapp_message(phone_number, response.content) # type: ignore
173
170
 
174
171
  except Exception as e:
175
172
  log_error(f"Error processing message: {str(e)}")
@@ -0,0 +1,29 @@
1
+ from typing import Optional
2
+
3
+ from fastapi.routing import APIRouter
4
+
5
+ from agno.agent import Agent
6
+ from agno.os.interfaces.base import BaseInterface
7
+ from agno.os.interfaces.whatsapp.router import attach_routes
8
+ from agno.team import Team
9
+
10
+
11
+ class Whatsapp(BaseInterface):
12
+ type = "whatsapp"
13
+
14
+ router: APIRouter
15
+
16
+ def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
17
+ self.agent = agent
18
+ self.team = team
19
+
20
+ if not self.agent and not self.team:
21
+ raise ValueError("Whatsapp requires an agent and a team")
22
+
23
+ def get_router(self, **kwargs) -> APIRouter:
24
+ # Cannot be overridden
25
+ self.router = APIRouter(prefix="/whatsapp", tags=["Whatsapp"])
26
+
27
+ self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
28
+
29
+ return self.router