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