agno 1.8.1__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +11 -66
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1743 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1432 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +882 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1045 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1416 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +15 -11
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1551 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +46 -151
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +85 -47
  158. agno/models/openai/chat.py +154 -37
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +15 -9
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +497 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +77 -33
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +32 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,448 +0,0 @@
1
- import json
2
- from dataclasses import asdict
3
- from io import BytesIO
4
- from typing import Any, Dict, Generator, List, Optional, Union, cast
5
- from uuid import uuid4
6
-
7
- from fastapi import APIRouter, File, Form, HTTPException, Query, UploadFile
8
- from fastapi.responses import StreamingResponse
9
-
10
- from agno.agent.agent import Agent, RunResponse
11
- from agno.app.playground.utils import process_audio, process_document, process_image, process_video
12
- from agno.media import Audio, Image, Video
13
- from agno.media import File as FileMedia
14
- from agno.run.base import RunStatus
15
- from agno.run.response import RunResponseEvent
16
- from agno.run.team import RunResponseErrorEvent as TeamRunResponseErrorEvent
17
- from agno.run.team import TeamRunResponseEvent
18
- from agno.run.v2.workflow import WorkflowErrorEvent
19
- from agno.team.team import Team
20
- from agno.utils.log import logger
21
- from agno.workflow.v2.workflow import Workflow as WorkflowV2
22
- from agno.workflow.workflow import Workflow
23
-
24
-
25
- def agent_chat_response_streamer(
26
- agent: Agent,
27
- message: str,
28
- session_id: Optional[str] = None,
29
- user_id: Optional[str] = None,
30
- images: Optional[List[Image]] = None,
31
- audio: Optional[List[Audio]] = None,
32
- videos: Optional[List[Video]] = None,
33
- ) -> Generator:
34
- try:
35
- run_response = agent.run(
36
- message,
37
- session_id=session_id,
38
- user_id=user_id,
39
- images=images,
40
- audio=audio,
41
- videos=videos,
42
- stream=True,
43
- stream_intermediate_steps=True,
44
- )
45
- for run_response_chunk in run_response:
46
- run_response_chunk = cast(RunResponseEvent, run_response_chunk)
47
- yield run_response_chunk.to_json()
48
- except Exception as e:
49
- error_response = RunResponse(content=str(e), status=RunStatus.error)
50
- yield error_response.to_json()
51
- return
52
-
53
-
54
- def team_chat_response_streamer(
55
- team: Team,
56
- message: str,
57
- session_id: Optional[str] = None,
58
- user_id: Optional[str] = None,
59
- images: Optional[List[Image]] = None,
60
- audio: Optional[List[Audio]] = None,
61
- videos: Optional[List[Video]] = None,
62
- files: Optional[List[FileMedia]] = None,
63
- ) -> Generator:
64
- try:
65
- run_response = team.run(
66
- message,
67
- session_id=session_id,
68
- user_id=user_id,
69
- images=images,
70
- audio=audio,
71
- videos=videos,
72
- files=files,
73
- stream=True,
74
- stream_intermediate_steps=True,
75
- )
76
- for run_response_chunk in run_response:
77
- run_response_chunk = cast(TeamRunResponseEvent, run_response_chunk)
78
- yield run_response_chunk.to_json()
79
- except Exception as e:
80
- error_response = TeamRunResponseErrorEvent(
81
- content=str(e),
82
- )
83
- yield error_response.to_json()
84
- return
85
-
86
-
87
- def workflow_response_streamer(
88
- workflow: WorkflowV2,
89
- body: Union[Dict[str, Any], str],
90
- session_id: Optional[str] = None,
91
- user_id: Optional[str] = None,
92
- ) -> Generator:
93
- try:
94
- if isinstance(body, dict):
95
- run_response = workflow.run(
96
- **body,
97
- user_id=user_id,
98
- session_id=session_id,
99
- stream=True,
100
- stream_intermediate_steps=True,
101
- )
102
- else:
103
- run_response = workflow.run(
104
- body,
105
- user_id=user_id,
106
- session_id=session_id,
107
- stream=True,
108
- stream_intermediate_steps=True,
109
- )
110
- for run_response_chunk in run_response:
111
- yield run_response_chunk.to_json()
112
- except Exception as e:
113
- import traceback
114
-
115
- traceback.print_exc(limit=3)
116
- error_response = WorkflowErrorEvent(
117
- error=str(e),
118
- )
119
- yield error_response.to_json()
120
- return
121
-
122
-
123
- def get_sync_router(
124
- agents: Optional[List[Agent]] = None, teams: Optional[List[Team]] = None, workflows: Optional[List[Workflow]] = None
125
- ) -> APIRouter:
126
- router = APIRouter()
127
-
128
- if agents is None and teams is None and workflows is None:
129
- raise ValueError("Either agents, teams or workflows must be provided.")
130
-
131
- @router.get("/status")
132
- def status():
133
- return {"status": "available"}
134
-
135
- def agent_process_file(
136
- files: List[UploadFile],
137
- agent: Agent,
138
- ):
139
- base64_images: List[Image] = []
140
- base64_audios: List[Audio] = []
141
- base64_videos: List[Video] = []
142
- for file in files:
143
- logger.info(f"Processing file: {file.content_type}")
144
- if file.content_type in ["image/png", "image/jpeg", "image/jpg", "image/webp"]:
145
- try:
146
- base64_image = process_image(file)
147
- base64_images.append(base64_image)
148
- except Exception as e:
149
- logger.error(f"Error processing image {file.filename}: {e}")
150
- continue
151
- elif file.content_type in ["audio/wav", "audio/mp3", "audio/mpeg"]:
152
- try:
153
- base64_audio = process_audio(file)
154
- base64_audios.append(base64_audio)
155
- except Exception as e:
156
- logger.error(f"Error processing audio {file.filename}: {e}")
157
- continue
158
- elif file.content_type in [
159
- "video/x-flv",
160
- "video/quicktime",
161
- "video/mpeg",
162
- "video/mpegs",
163
- "video/mpgs",
164
- "video/mpg",
165
- "video/mpg",
166
- "video/mp4",
167
- "video/webm",
168
- "video/wmv",
169
- "video/3gpp",
170
- ]:
171
- try:
172
- base64_video = process_video(file)
173
- base64_videos.append(base64_video)
174
- except Exception as e:
175
- logger.error(f"Error processing video {file.filename}: {e}")
176
- continue
177
- else:
178
- # Check for knowledge base before processing documents
179
- if agent.knowledge is None:
180
- raise HTTPException(status_code=404, detail="KnowledgeBase not found")
181
-
182
- if file.content_type == "application/pdf":
183
- from agno.document.reader.pdf_reader import PDFReader
184
-
185
- contents = file.file.read()
186
- pdf_file = BytesIO(contents)
187
- pdf_file.name = file.filename
188
- file_content = PDFReader().read(pdf_file)
189
- if agent.knowledge is not None:
190
- agent.knowledge.load_documents(file_content)
191
- elif file.content_type == "text/csv":
192
- from agno.document.reader.csv_reader import CSVReader
193
-
194
- contents = file.file.read()
195
- csv_file = BytesIO(contents)
196
- csv_file.name = file.filename
197
- file_content = CSVReader().read(csv_file)
198
- if agent.knowledge is not None:
199
- agent.knowledge.load_documents(file_content)
200
- elif file.content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
201
- from agno.document.reader.docx_reader import DocxReader
202
-
203
- contents = file.file.read()
204
- docx_file = BytesIO(contents)
205
- docx_file.name = file.filename
206
- file_content = DocxReader().read(docx_file)
207
- if agent.knowledge is not None:
208
- agent.knowledge.load_documents(file_content)
209
- elif file.content_type == "text/plain":
210
- from agno.document.reader.text_reader import TextReader
211
-
212
- contents = file.file.read()
213
- text_file = BytesIO(contents)
214
- text_file.name = file.filename
215
- file_content = TextReader().read(text_file)
216
- if agent.knowledge is not None:
217
- agent.knowledge.load_documents(file_content)
218
-
219
- elif file.content_type == "application/json":
220
- from agno.document.reader.json_reader import JSONReader
221
-
222
- contents = file.file.read()
223
- json_file = BytesIO(contents)
224
- json_file.name = file.filename
225
- file_content = JSONReader().read(json_file)
226
- if agent.knowledge is not None:
227
- agent.knowledge.load_documents(file_content)
228
- else:
229
- raise HTTPException(status_code=400, detail="Unsupported file type")
230
-
231
- return base64_images, base64_audios, base64_videos
232
-
233
- def team_process_file(
234
- files: List[UploadFile],
235
- ):
236
- base64_images: List[Image] = []
237
- base64_audios: List[Audio] = []
238
- base64_videos: List[Video] = []
239
- document_files: List[FileMedia] = []
240
- for file in files:
241
- if file.content_type in ["image/png", "image/jpeg", "image/jpg", "image/webp"]:
242
- try:
243
- base64_image = process_image(file)
244
- base64_images.append(base64_image)
245
- except Exception as e:
246
- logger.error(f"Error processing image {file.filename}: {e}")
247
- continue
248
- elif file.content_type in ["audio/wav", "audio/mp3", "audio/mpeg"]:
249
- try:
250
- base64_audio = process_audio(file)
251
- base64_audios.append(base64_audio)
252
- except Exception as e:
253
- logger.error(f"Error processing audio {file.filename}: {e}")
254
- continue
255
- elif file.content_type in [
256
- "video/x-flv",
257
- "video/quicktime",
258
- "video/mpeg",
259
- "video/mpegs",
260
- "video/mpgs",
261
- "video/mpg",
262
- "video/mpg",
263
- "video/mp4",
264
- "video/webm",
265
- "video/wmv",
266
- "video/3gpp",
267
- ]:
268
- try:
269
- base64_video = process_video(file)
270
- base64_videos.append(base64_video)
271
- except Exception as e:
272
- logger.error(f"Error processing video {file.filename}: {e}")
273
- continue
274
- elif file.content_type in [
275
- "application/pdf",
276
- "text/csv",
277
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
278
- "text/plain",
279
- "application/json",
280
- ]:
281
- document_file = process_document(file)
282
- if document_file is not None:
283
- document_files.append(document_file)
284
- else:
285
- raise HTTPException(status_code=400, detail="Unsupported file type")
286
-
287
- return base64_images, base64_audios, base64_videos, document_files
288
-
289
- @router.post("/runs")
290
- def run_agent_or_team_or_workflow(
291
- message: str = Form(None),
292
- stream: bool = Form(False),
293
- monitor: bool = Form(False),
294
- agent_id: Optional[str] = Query(None),
295
- team_id: Optional[str] = Query(None),
296
- workflow_id: Optional[str] = Query(None),
297
- workflow_input: Optional[str] = Form(None),
298
- session_id: Optional[str] = Form(None),
299
- user_id: Optional[str] = Form(None),
300
- files: Optional[List[UploadFile]] = File(None),
301
- ):
302
- if session_id is not None and session_id != "":
303
- logger.debug(f"Continuing session: {session_id}")
304
- else:
305
- logger.debug("Creating new session")
306
- session_id = str(uuid4())
307
-
308
- # Only one of agent_id, team_id or workflow_id can be provided
309
- if agent_id and team_id or agent_id and workflow_id or team_id and workflow_id:
310
- raise HTTPException(status_code=400, detail="Only one of agent_id, team_id or workflow_id can be provided")
311
-
312
- if not agent_id and not team_id and not workflow_id:
313
- raise HTTPException(status_code=400, detail="One of agent_id, team_id or workflow_id must be provided")
314
-
315
- agent = None
316
- team = None
317
- workflow = None
318
-
319
- if agent_id and agents:
320
- agent = next((agent for agent in agents if agent.agent_id == agent_id), None)
321
- if agent is None:
322
- raise HTTPException(status_code=404, detail="Agent not found")
323
- if not message:
324
- raise HTTPException(status_code=400, detail="Message is required")
325
- if team_id and teams:
326
- team = next((team for team in teams if team.team_id == team_id), None)
327
- if team is None:
328
- raise HTTPException(status_code=404, detail="Team not found")
329
- if not message:
330
- raise HTTPException(status_code=400, detail="Message is required")
331
- if workflow_id and workflows:
332
- workflow = next((workflow for workflow in workflows if workflow.workflow_id == workflow_id), None)
333
- if workflow is None:
334
- raise HTTPException(status_code=404, detail="Workflow not found")
335
- if not workflow_input:
336
- raise HTTPException(status_code=400, detail="Workflow input is required")
337
-
338
- # Parse workflow_input into a dict if it is a valid JSON
339
- try:
340
- parsed_workflow_input = json.loads(workflow_input)
341
- workflow_input = parsed_workflow_input
342
- except json.JSONDecodeError:
343
- pass
344
-
345
- if agent:
346
- agent.monitoring = bool(monitor)
347
- elif team:
348
- team.monitoring = bool(monitor)
349
- elif workflow:
350
- workflow.monitoring = bool(monitor)
351
-
352
- if files:
353
- if agent:
354
- base64_images, base64_audios, base64_videos = agent_process_file(files, agent)
355
- elif team:
356
- base64_images, base64_audios, base64_videos, document_files = team_process_file(files)
357
-
358
- if stream:
359
- if agent:
360
- return StreamingResponse(
361
- agent_chat_response_streamer(
362
- agent,
363
- message,
364
- session_id=session_id,
365
- user_id=user_id,
366
- images=base64_images if base64_images else None,
367
- audio=base64_audios if base64_audios else None,
368
- videos=base64_videos if base64_videos else None,
369
- ),
370
- media_type="text/event-stream",
371
- )
372
- elif team:
373
- return StreamingResponse(
374
- team_chat_response_streamer(
375
- team,
376
- message,
377
- session_id=session_id,
378
- user_id=user_id,
379
- images=base64_images if base64_images else None,
380
- audio=base64_audios if base64_audios else None,
381
- videos=base64_videos if base64_videos else None,
382
- files=document_files if document_files else None,
383
- ),
384
- media_type="text/event-stream",
385
- )
386
- elif workflow:
387
- if isinstance(workflow, Workflow):
388
- workflow_instance = workflow.deep_copy(update={"workflow_id": workflow_id})
389
- workflow_instance.user_id = user_id
390
- workflow_instance.session_name = None
391
- if isinstance(workflow_input, dict):
392
- return StreamingResponse(
393
- (json.dumps(asdict(result)) for result in workflow_instance.run(**workflow_input)),
394
- media_type="text/event-stream",
395
- )
396
- else:
397
- return StreamingResponse(
398
- (json.dumps(asdict(result)) for result in workflow_instance.run(workflow_input)), # type: ignore
399
- media_type="text/event-stream",
400
- )
401
- else:
402
- return StreamingResponse(
403
- workflow_response_streamer(workflow, workflow_input, session_id=session_id, user_id=user_id),
404
- media_type="text/event-stream",
405
- )
406
- else:
407
- if agent:
408
- run_response = cast(
409
- RunResponse,
410
- agent.run(
411
- message=message,
412
- session_id=session_id,
413
- user_id=user_id,
414
- images=base64_images if base64_images else None,
415
- audio=base64_audios if base64_audios else None,
416
- videos=base64_videos if base64_videos else None,
417
- stream=False,
418
- ),
419
- )
420
- return run_response.to_dict()
421
- elif team:
422
- team_run_response = team.run(
423
- message=message,
424
- session_id=session_id,
425
- user_id=user_id,
426
- images=base64_images if base64_images else None,
427
- audio=base64_audios if base64_audios else None,
428
- videos=base64_videos if base64_videos else None,
429
- files=document_files if document_files else None,
430
- stream=False,
431
- )
432
- return team_run_response.to_dict()
433
- elif workflow:
434
- if isinstance(workflow, Workflow):
435
- workflow_instance = workflow.deep_copy(update={"workflow_id": workflow_id})
436
- workflow_instance.user_id = user_id
437
- workflow_instance.session_name = None
438
- if isinstance(workflow_input, dict):
439
- return workflow_instance.run(**workflow_input).to_dict()
440
- else:
441
- return workflow_instance.run(workflow_input).to_dict() # type: ignore
442
- else:
443
- if isinstance(workflow_input, dict):
444
- return workflow.run(**workflow_input, session_id=session_id, user_id=user_id).to_dict()
445
- else:
446
- return workflow.run(workflow_input, session_id=session_id, user_id=user_id).to_dict()
447
-
448
- return router
@@ -1,228 +0,0 @@
1
- from os import getenv
2
- from typing import Any, Callable, Dict, List, Optional, Union
3
- from urllib.parse import quote
4
- from uuid import uuid4
5
-
6
- from fastapi import FastAPI, HTTPException
7
- from fastapi.responses import JSONResponse
8
- from fastapi.routing import APIRouter
9
- from rich import box
10
- from rich.panel import Panel
11
- from starlette.middleware.cors import CORSMiddleware
12
- from starlette.requests import Request
13
-
14
- from agno.agent.agent import Agent
15
- from agno.api.playground import PlaygroundEndpointCreate
16
- from agno.app.playground.async_router import get_async_playground_router
17
- from agno.app.playground.sync_router import get_sync_playground_router
18
- from agno.app.utils import generate_id
19
- from agno.cli.console import console
20
- from agno.cli.settings import agno_cli_settings
21
- from agno.playground.settings import PlaygroundSettings
22
- from agno.team.team import Team
23
- from agno.utils.log import log_debug, logger
24
- from agno.workflow.workflow import Workflow
25
-
26
-
27
- class Playground:
28
- def __init__(
29
- self,
30
- agents: Optional[List[Agent]] = None,
31
- teams: Optional[List[Team]] = None,
32
- workflows: Optional[List[Workflow]] = None,
33
- settings: Optional[PlaygroundSettings] = None,
34
- api_app: Optional[FastAPI] = None,
35
- router: Optional[APIRouter] = None,
36
- app_id: Optional[str] = None,
37
- name: Optional[str] = None,
38
- description: Optional[str] = None,
39
- monitoring: bool = True,
40
- ):
41
- if not agents and not workflows and not teams:
42
- raise ValueError("Either agents, teams or workflows must be provided.")
43
-
44
- self.agents: Optional[List[Agent]] = agents
45
- self.workflows: Optional[List[Workflow]] = workflows
46
- self.teams: Optional[List[Team]] = teams
47
-
48
- self.settings: PlaygroundSettings = settings or PlaygroundSettings()
49
- self.api_app: Optional[FastAPI] = api_app
50
- self.router: Optional[APIRouter] = router
51
-
52
- self.endpoints_created: Optional[PlaygroundEndpointCreate] = None
53
-
54
- self.app_id: Optional[str] = app_id
55
- self.name: Optional[str] = name
56
- self.monitoring = monitoring
57
- self.description = description
58
- self.set_app_id()
59
- if self.agents:
60
- for agent in self.agents:
61
- if not agent.app_id:
62
- agent.app_id = self.app_id
63
- agent.initialize_agent()
64
- # Required for playground to work
65
- agent.store_events = True
66
-
67
- if self.teams:
68
- for team in self.teams:
69
- if not team.app_id:
70
- team.app_id = self.app_id
71
- team.initialize_team()
72
- # Required for playground to work
73
- team.store_events = True
74
- for member in team.members:
75
- if isinstance(member, Agent):
76
- if not member.app_id:
77
- member.app_id = self.app_id
78
-
79
- member.team_id = None
80
- member.initialize_agent()
81
- elif isinstance(member, Team):
82
- member.initialize_team()
83
-
84
- if self.workflows:
85
- for workflow in self.workflows:
86
- if hasattr(workflow, "app_id") and not workflow.app_id:
87
- workflow.app_id = self.app_id
88
- if not workflow.workflow_id:
89
- workflow.workflow_id = generate_id(workflow.name)
90
- workflow.initialize_workflow()
91
-
92
- def set_app_id(self) -> str:
93
- # If app_id is already set, keep it instead of overriding with UUID
94
- if self.app_id is None:
95
- self.app_id = str(uuid4())
96
-
97
- # Don't override existing app_id
98
- return self.app_id
99
-
100
- def _set_monitoring(self) -> None:
101
- """Override monitoring and telemetry settings based on environment variables."""
102
-
103
- # Only override if the environment variable is set
104
- monitor_env = getenv("AGNO_MONITOR")
105
- if monitor_env is not None:
106
- self.monitoring = monitor_env.lower() == "true"
107
-
108
- def get_router(self) -> APIRouter:
109
- return get_sync_playground_router(self.agents, self.workflows, self.teams, self.app_id)
110
-
111
- def get_async_router(self) -> APIRouter:
112
- return get_async_playground_router(self.agents, self.workflows, self.teams, self.app_id)
113
-
114
- def get_app(self, use_async: bool = True, prefix: str = "/v1", lifespan: Optional[Callable] = None) -> FastAPI:
115
- if not self.api_app:
116
- self.api_app = FastAPI(
117
- title=self.settings.title,
118
- docs_url="/docs" if self.settings.docs_enabled else None,
119
- redoc_url="/redoc" if self.settings.docs_enabled else None,
120
- openapi_url="/openapi.json" if self.settings.docs_enabled else None,
121
- lifespan=lifespan,
122
- )
123
-
124
- if not self.api_app:
125
- raise Exception("API App could not be created.")
126
-
127
- @self.api_app.exception_handler(HTTPException)
128
- async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
129
- return JSONResponse(
130
- status_code=exc.status_code,
131
- content={"detail": str(exc.detail)},
132
- )
133
-
134
- async def general_exception_handler(request: Request, call_next):
135
- try:
136
- return await call_next(request)
137
- except Exception as e:
138
- return JSONResponse(
139
- status_code=e.status_code if hasattr(e, "status_code") else 500,
140
- content={"detail": str(e)},
141
- )
142
-
143
- self.api_app.middleware("http")(general_exception_handler)
144
-
145
- if not self.router:
146
- self.router = APIRouter(prefix=prefix)
147
-
148
- if not self.router:
149
- raise Exception("API Router could not be created.")
150
-
151
- if use_async:
152
- self.router.include_router(self.get_async_router())
153
- else:
154
- self.router.include_router(self.get_router())
155
- self.api_app.include_router(self.router)
156
-
157
- self.api_app.add_middleware(
158
- CORSMiddleware,
159
- allow_origins=self.settings.cors_origin_list,
160
- allow_credentials=True,
161
- allow_methods=["*"],
162
- allow_headers=["*"],
163
- expose_headers=["*"],
164
- )
165
-
166
- return self.api_app
167
-
168
- def serve(
169
- self,
170
- app: Union[str, FastAPI],
171
- *,
172
- scheme: str = "http",
173
- host: str = "localhost",
174
- port: int = 7777,
175
- reload: bool = False,
176
- prefix="/v1",
177
- **kwargs,
178
- ):
179
- import uvicorn
180
-
181
- logger.info(f"Starting playground on {scheme}://{host}:{port}")
182
- # Encode the full endpoint (host:port)
183
- encoded_endpoint = quote(f"{host}:{port}{prefix}")
184
- self.endpoints_created = PlaygroundEndpointCreate(
185
- endpoint=f"{scheme}://{host}:{port}", playground_data={"prefix": prefix}
186
- )
187
-
188
- # Create a panel with the playground URL
189
- url = f"{agno_cli_settings.playground_url}?endpoint={encoded_endpoint}"
190
- panel = Panel(
191
- f"[bold green]Playground URL:[/bold green] [link={url}]{url}[/link]",
192
- title="Agent Playground",
193
- expand=False,
194
- border_style="cyan",
195
- box=box.HEAVY,
196
- padding=(2, 2),
197
- )
198
-
199
- # Print the panel
200
- console.print(panel)
201
- self.set_app_id()
202
-
203
- self.register_app_on_platform()
204
-
205
- uvicorn.run(app=app, host=host, port=port, reload=reload, **kwargs)
206
-
207
- def register_app_on_platform(self) -> None:
208
- self._set_monitoring()
209
- if not self.monitoring:
210
- return
211
-
212
- from agno.api.app import AppCreate, create_app
213
-
214
- try:
215
- log_debug(f"Creating app on Platform: {self.name}, {self.app_id}")
216
- create_app(app=AppCreate(name=self.name, app_id=self.app_id, config=self.to_dict()))
217
- except Exception as e:
218
- log_debug(f"Could not create Agent app: {e}")
219
- log_debug(f"Agent app created: {self.name}, {self.app_id}")
220
-
221
- def to_dict(self) -> Dict[str, Any]:
222
- payload = {
223
- "endpointData": self.endpoints_created.model_dump(exclude_none=True) if self.endpoints_created else {},
224
- "type": "playground",
225
- "description": self.description,
226
- }
227
- payload = {k: v for k, v in payload.items() if v is not None}
228
- return payload