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,1042 +0,0 @@
1
- import json
2
- from io import BytesIO
3
- from typing import Any, Dict, Generator, List, Optional, cast
4
- from uuid import uuid4
5
-
6
- from fastapi import APIRouter, File, Form, HTTPException, Query, UploadFile
7
- from fastapi.responses import JSONResponse, StreamingResponse
8
-
9
- from agno.agent.agent import Agent, RunResponse
10
- from agno.app.playground.operator import (
11
- format_tools,
12
- get_agent_by_id,
13
- get_session_title,
14
- get_session_title_from_team_session,
15
- get_session_title_from_workflow_session,
16
- get_team_by_id,
17
- get_workflow_by_id,
18
- )
19
- from agno.app.playground.schemas import (
20
- AgentGetResponse,
21
- AgentModel,
22
- AgentRenameRequest,
23
- AgentSessionsResponse,
24
- MemoryResponse,
25
- TeamGetResponse,
26
- TeamRenameRequest,
27
- TeamSessionResponse,
28
- WorkflowGetResponse,
29
- WorkflowRenameRequest,
30
- WorkflowRunRequest,
31
- WorkflowSessionResponse,
32
- WorkflowsGetResponse,
33
- )
34
- from agno.app.playground.utils import process_audio, process_document, process_image, process_video
35
- from agno.media import Audio, Image, Video
36
- from agno.media import File as FileMedia
37
- from agno.memory.agent import AgentMemory
38
- from agno.memory.v2 import Memory
39
- from agno.run.response import RunResponseErrorEvent, RunResponseEvent
40
- from agno.run.team import RunResponseErrorEvent as TeamRunResponseErrorEvent
41
- from agno.run.v2.workflow import WorkflowErrorEvent
42
- from agno.storage.session.agent import AgentSession
43
- from agno.storage.session.team import TeamSession
44
- from agno.storage.session.workflow import WorkflowSession
45
- from agno.team.team import Team
46
- from agno.utils.log import logger
47
- from agno.workflow.v2.workflow import Workflow as WorkflowV2
48
- from agno.workflow.workflow import Workflow
49
-
50
-
51
- def chat_response_streamer(
52
- agent: Agent,
53
- message: str,
54
- session_id: Optional[str] = None,
55
- user_id: Optional[str] = None,
56
- images: Optional[List[Image]] = None,
57
- audio: Optional[List[Audio]] = None,
58
- videos: Optional[List[Video]] = None,
59
- files: Optional[List[FileMedia]] = None,
60
- ) -> Generator:
61
- try:
62
- run_response = agent.run(
63
- message,
64
- session_id=session_id,
65
- user_id=user_id,
66
- images=images,
67
- audio=audio,
68
- videos=videos,
69
- files=files,
70
- stream=True,
71
- stream_intermediate_steps=True,
72
- )
73
- for run_response_chunk in run_response:
74
- run_response_chunk = cast(RunResponseEvent, run_response_chunk)
75
- yield run_response_chunk.to_json()
76
- except Exception as e:
77
- import traceback
78
-
79
- traceback.print_exc(limit=3)
80
- error_response = RunResponseErrorEvent(
81
- content=str(e),
82
- )
83
- yield error_response.to_json()
84
- return
85
-
86
-
87
- def agent_continue_run_streamer(
88
- agent: Agent,
89
- run_id: Optional[str] = None,
90
- updated_tools: Optional[List] = None,
91
- session_id: Optional[str] = None,
92
- user_id: Optional[str] = None,
93
- ) -> Generator:
94
- try:
95
- continue_response = agent.continue_run(
96
- run_id=run_id,
97
- updated_tools=updated_tools,
98
- session_id=session_id,
99
- user_id=user_id,
100
- stream=True,
101
- stream_intermediate_steps=True,
102
- )
103
- for run_response_chunk in continue_response:
104
- run_response_chunk = cast(RunResponseEvent, run_response_chunk)
105
- yield run_response_chunk.to_json()
106
- except Exception as e:
107
- import traceback
108
-
109
- traceback.print_exc(limit=3)
110
- error_response = RunResponseErrorEvent(
111
- content=str(e),
112
- )
113
- yield error_response.to_json()
114
- return
115
-
116
-
117
- def team_chat_response_streamer(
118
- team: Team,
119
- message: str,
120
- session_id: Optional[str] = None,
121
- user_id: Optional[str] = None,
122
- images: Optional[List[Image]] = None,
123
- audio: Optional[List[Audio]] = None,
124
- videos: Optional[List[Video]] = None,
125
- files: Optional[List[FileMedia]] = None,
126
- ) -> Generator:
127
- try:
128
- run_response = team.run(
129
- message,
130
- session_id=session_id,
131
- user_id=user_id,
132
- images=images,
133
- audio=audio,
134
- videos=videos,
135
- files=files,
136
- stream=True,
137
- stream_intermediate_steps=True,
138
- )
139
- for run_response_chunk in run_response:
140
- yield run_response_chunk.to_json()
141
- except Exception as e:
142
- import traceback
143
-
144
- traceback.print_exc(limit=3)
145
- error_response = TeamRunResponseErrorEvent(
146
- content=str(e),
147
- )
148
- yield error_response.to_json()
149
- return
150
-
151
-
152
- def workflow_response_streamer(
153
- workflow: WorkflowV2,
154
- body: WorkflowRunRequest,
155
- ) -> Generator:
156
- try:
157
- run_response = workflow.run(
158
- **body.input,
159
- user_id=body.user_id,
160
- session_id=body.session_id or str(uuid4()),
161
- stream=True,
162
- stream_intermediate_steps=True,
163
- )
164
- for run_response_chunk in run_response:
165
- yield run_response_chunk.to_json()
166
- except Exception as e:
167
- import traceback
168
-
169
- traceback.print_exc(limit=3)
170
- error_response = WorkflowErrorEvent(
171
- error=str(e),
172
- )
173
- yield error_response.to_json()
174
- return
175
-
176
-
177
- def get_sync_playground_router(
178
- agents: Optional[List[Agent]] = None,
179
- workflows: Optional[List[Workflow]] = None,
180
- teams: Optional[List[Team]] = None,
181
- active_app_id: Optional[str] = None,
182
- ) -> APIRouter:
183
- playground_router = APIRouter(prefix="/playground", tags=["Playground"])
184
- if agents is None and workflows is None and teams is None:
185
- raise ValueError("Either agents, teams or workflows must be provided.")
186
-
187
- @playground_router.get("/status")
188
- def playground_status(app_id: Optional[str] = None):
189
- if app_id is None:
190
- return {"playground": "available"}
191
- else:
192
- if active_app_id == app_id:
193
- return {"playground": "available"}
194
- else:
195
- raise HTTPException(status_code=404, detail="Playground not available")
196
-
197
- @playground_router.get("/agents", response_model=List[AgentGetResponse])
198
- def get_agents():
199
- agent_list: List[AgentGetResponse] = []
200
- if agents is None:
201
- return agent_list
202
-
203
- for agent in agents:
204
- # We can make up a session_id here because we aren't really using the tools
205
- agent_tools = agent.get_tools(session_id=str(uuid4()))
206
- formatted_tools = format_tools(agent_tools)
207
-
208
- name = agent.model.name or agent.model.__class__.__name__ if agent.model else None
209
- provider = agent.model.provider or agent.model.__class__.__name__ if agent.model else None
210
- model_id = agent.model.id if agent.model else None
211
-
212
- # Create an agent_id if its not set on the agent
213
- if agent.agent_id is None:
214
- agent.set_agent_id()
215
-
216
- if provider and model_id:
217
- provider = f"{provider} {model_id}"
218
- elif name and model_id:
219
- provider = f"{name} {model_id}"
220
- elif model_id:
221
- provider = model_id
222
- else:
223
- provider = ""
224
-
225
- if agent.memory:
226
- memory_dict: Optional[Dict[str, Any]] = {}
227
- if isinstance(agent.memory, AgentMemory) and agent.memory.db:
228
- memory_dict = {"name": agent.memory.db.__class__.__name__}
229
- elif isinstance(agent.memory, Memory) and agent.memory.db:
230
- memory_dict = {"name": "Memory"}
231
- if agent.memory.model is not None:
232
- memory_dict["model"] = AgentModel(
233
- name=agent.memory.model.name,
234
- model=agent.memory.model.id,
235
- provider=agent.memory.model.provider,
236
- )
237
- else:
238
- memory_dict["model"] = AgentModel(
239
- name=name,
240
- model=model_id,
241
- provider=provider,
242
- )
243
- if agent.memory.db is not None:
244
- memory_dict["db"] = agent.memory.db.__dict__() # type: ignore
245
-
246
- else:
247
- memory_dict = None
248
- else:
249
- memory_dict = None
250
-
251
- agent_list.append(
252
- AgentGetResponse(
253
- agent_id=agent.agent_id,
254
- name=agent.name,
255
- model=AgentModel(
256
- name=name,
257
- model=model_id,
258
- provider=provider,
259
- ),
260
- add_context=agent.add_context,
261
- tools=formatted_tools,
262
- memory=memory_dict,
263
- storage={"name": agent.storage.__class__.__name__} if agent.storage else None,
264
- knowledge={"name": agent.knowledge.__class__.__name__} if agent.knowledge else None,
265
- description=agent.description,
266
- instructions=agent.instructions,
267
- )
268
- )
269
-
270
- return agent_list
271
-
272
- @playground_router.post("/agents/{agent_id}/runs")
273
- def create_agent_run(
274
- agent_id: str,
275
- message: str = Form(...),
276
- stream: bool = Form(True),
277
- monitor: bool = Form(False),
278
- session_id: Optional[str] = Form(None),
279
- user_id: Optional[str] = Form(None),
280
- files: Optional[List[UploadFile]] = File(None),
281
- ):
282
- logger.debug(f"AgentRunRequest: {message} {agent_id} {stream} {monitor} {session_id} {user_id} {files}")
283
- agent = get_agent_by_id(agent_id, agents)
284
- if agent is None:
285
- raise HTTPException(status_code=404, detail="Agent not found")
286
-
287
- if session_id is not None and session_id != "":
288
- logger.debug(f"Continuing session: {session_id}")
289
- else:
290
- logger.debug("Creating new session")
291
- session_id = str(uuid4())
292
-
293
- if monitor:
294
- agent.monitoring = True
295
- else:
296
- agent.monitoring = False
297
-
298
- base64_images: List[Image] = []
299
- base64_audios: List[Audio] = []
300
- base64_videos: List[Video] = []
301
- input_files: List[FileMedia] = []
302
-
303
- if files:
304
- for file in files:
305
- if file.content_type in ["image/png", "image/jpeg", "image/jpg", "image/webp"]:
306
- try:
307
- base64_image = process_image(file)
308
- base64_images.append(base64_image)
309
- except Exception as e:
310
- logger.error(f"Error processing image {file.filename}: {e}")
311
- continue
312
- elif file.content_type in ["audio/wav", "audio/mp3", "audio/mpeg"]:
313
- try:
314
- base64_audio = process_audio(file)
315
- base64_audios.append(base64_audio)
316
- except Exception as e:
317
- logger.error(f"Error processing audio {file.filename}: {e}")
318
- continue
319
- elif file.content_type in [
320
- "video/x-flv",
321
- "video/quicktime",
322
- "video/mpeg",
323
- "video/mpegs",
324
- "video/mpgs",
325
- "video/mpg",
326
- "video/mpg",
327
- "video/mp4",
328
- "video/webm",
329
- "video/wmv",
330
- "video/3gpp",
331
- ]:
332
- try:
333
- base64_video = process_video(file)
334
- base64_videos.append(base64_video)
335
- except Exception as e:
336
- logger.error(f"Error processing video {file.filename}: {e}")
337
- continue
338
- else:
339
- # Process document files
340
-
341
- if file.content_type == "application/pdf":
342
- from agno.document.reader.pdf_reader import PDFReader
343
-
344
- contents = file.file.read()
345
-
346
- # If agent has knowledge base, load the document into it
347
- if agent.knowledge is not None:
348
- pdf_file = BytesIO(contents)
349
- pdf_file.name = file.filename
350
- file_content = PDFReader().read(pdf_file)
351
- agent.knowledge.load_documents(file_content)
352
- else:
353
- # If no knowledge base, treat as direct file input (similar to cookbook examples)
354
- input_files.append(FileMedia(content=contents))
355
-
356
- elif file.content_type == "text/csv":
357
- from agno.document.reader.csv_reader import CSVReader
358
-
359
- contents = file.file.read()
360
-
361
- # If agent has knowledge base, load the document into it
362
- if agent.knowledge is not None:
363
- csv_file = BytesIO(contents)
364
- csv_file.name = file.filename
365
- file_content = CSVReader().read(csv_file)
366
- agent.knowledge.load_documents(file_content)
367
- else:
368
- # If no knowledge base, treat as direct file input
369
- input_files.append(FileMedia(content=contents))
370
-
371
- elif file.content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
372
- from agno.document.reader.docx_reader import DocxReader
373
-
374
- contents = file.file.read()
375
-
376
- # If agent has knowledge base, load the document into it
377
- if agent.knowledge is not None:
378
- docx_file = BytesIO(contents)
379
- docx_file.name = file.filename
380
- file_content = DocxReader().read(docx_file)
381
- agent.knowledge.load_documents(file_content)
382
- else:
383
- # If no knowledge base, treat as direct file input
384
- input_files.append(FileMedia(content=contents))
385
-
386
- elif file.content_type == "text/plain":
387
- from agno.document.reader.text_reader import TextReader
388
-
389
- contents = file.file.read()
390
-
391
- # If agent has knowledge base, load the document into it
392
- if agent.knowledge is not None:
393
- text_file = BytesIO(contents)
394
- text_file.name = file.filename
395
- file_content = TextReader().read(text_file)
396
- agent.knowledge.load_documents(file_content)
397
- else:
398
- # If no knowledge base, treat as direct file input
399
- input_files.append(FileMedia(content=contents))
400
-
401
- elif file.content_type == "application/json":
402
- from agno.document.reader.json_reader import JSONReader
403
-
404
- contents = file.file.read()
405
-
406
- # If agent has knowledge base, load the document into it
407
- if agent.knowledge is not None:
408
- json_file = BytesIO(contents)
409
- json_file.name = file.filename
410
- file_content = JSONReader().read(json_file)
411
- agent.knowledge.load_documents(file_content)
412
- else:
413
- # If no knowledge base, treat as direct file input
414
- input_files.append(FileMedia(content=contents))
415
- else:
416
- raise HTTPException(status_code=400, detail="Unsupported file type")
417
-
418
- if stream:
419
- return StreamingResponse(
420
- chat_response_streamer(
421
- agent,
422
- message,
423
- session_id=session_id,
424
- user_id=user_id,
425
- images=base64_images if base64_images else None,
426
- audio=base64_audios if base64_audios else None,
427
- videos=base64_videos if base64_videos else None,
428
- files=input_files if input_files else None,
429
- ),
430
- media_type="text/event-stream",
431
- )
432
- else:
433
- run_response = cast(
434
- RunResponse,
435
- agent.run(
436
- message=message,
437
- session_id=session_id,
438
- user_id=user_id,
439
- images=base64_images if base64_images else None,
440
- audio=base64_audios if base64_audios else None,
441
- videos=base64_videos if base64_videos else None,
442
- files=input_files if input_files else None,
443
- stream=False,
444
- ),
445
- )
446
- return run_response.to_dict()
447
-
448
- @playground_router.post("/agents/{agent_id}/runs/{run_id}/continue")
449
- def continue_agent_run(
450
- agent_id: str,
451
- run_id: str,
452
- tools: str = Form(...), # JSON string of tools
453
- session_id: Optional[str] = Form(None),
454
- user_id: Optional[str] = Form(None),
455
- stream: bool = Form(True),
456
- ):
457
- # Parse the JSON string manually
458
- try:
459
- tools_data = json.loads(tools) if tools else None
460
- except json.JSONDecodeError:
461
- raise HTTPException(status_code=400, detail="Invalid JSON in tools field")
462
-
463
- logger.debug(
464
- f"AgentContinueRunRequest: run_id={run_id} session_id={session_id} user_id={user_id} agent_id={agent_id}"
465
- )
466
- agent = get_agent_by_id(agent_id, agents)
467
- if agent is None:
468
- raise HTTPException(status_code=404, detail="Agent not found")
469
-
470
- if session_id is None or session_id == "":
471
- logger.warning(
472
- "Continuing run without session_id. This might lead to unexpected behavior if session context is important."
473
- )
474
- else:
475
- logger.debug(f"Continuing run within session: {session_id}")
476
-
477
- # Convert tools dict to ToolExecution objects if provided
478
- updated_tools = None
479
- if tools_data:
480
- try:
481
- from agno.models.response import ToolExecution
482
-
483
- updated_tools = [ToolExecution.from_dict(tool) for tool in tools_data]
484
- except Exception as e:
485
- raise HTTPException(status_code=400, detail=f"Invalid structure or content for tools: {str(e)}")
486
-
487
- if stream:
488
- return StreamingResponse(
489
- agent_continue_run_streamer(
490
- agent,
491
- run_id=run_id, # run_id from path
492
- updated_tools=updated_tools,
493
- session_id=session_id,
494
- user_id=user_id,
495
- ),
496
- media_type="text/event-stream",
497
- )
498
- else:
499
- run_response_obj = cast(
500
- RunResponse,
501
- agent.continue_run(
502
- run_id=run_id, # run_id from path
503
- updated_tools=updated_tools,
504
- session_id=session_id,
505
- user_id=user_id,
506
- stream=False,
507
- ),
508
- )
509
- return run_response_obj.to_dict()
510
-
511
- @playground_router.get("/agents/{agent_id}/sessions")
512
- def get_agent_sessions(agent_id: str, user_id: Optional[str] = Query(None, min_length=1)):
513
- logger.debug(f"AgentSessionsRequest: {agent_id} {user_id}")
514
- agent = get_agent_by_id(agent_id, agents)
515
- if agent is None:
516
- return JSONResponse(status_code=404, content="Agent not found.")
517
-
518
- if agent.storage is None:
519
- return JSONResponse(status_code=404, content="Agent does not have storage enabled.")
520
-
521
- agent_sessions: List[AgentSessionsResponse] = []
522
- all_agent_sessions: List[AgentSession] = agent.storage.get_all_sessions(user_id=user_id, entity_id=agent_id) # type: ignore
523
- for session in all_agent_sessions:
524
- title = get_session_title(session)
525
- agent_sessions.append(
526
- AgentSessionsResponse(
527
- title=title,
528
- session_id=session.session_id,
529
- session_name=session.session_data.get("session_name") if session.session_data else None,
530
- created_at=session.created_at,
531
- )
532
- )
533
- return agent_sessions
534
-
535
- @playground_router.get("/agents/{agent_id}/sessions/{session_id}")
536
- def get_agent_session(agent_id: str, session_id: str, user_id: Optional[str] = Query(None, min_length=1)):
537
- logger.debug(f"AgentSessionsRequest: {agent_id} {user_id} {session_id}")
538
- agent = get_agent_by_id(agent_id, agents)
539
- if agent is None:
540
- return JSONResponse(status_code=404, content="Agent not found.")
541
-
542
- if agent.storage is None:
543
- return JSONResponse(status_code=404, content="Agent does not have storage enabled.")
544
-
545
- agent_session: Optional[AgentSession] = agent.storage.read(session_id) # type: ignore
546
- if agent_session is None:
547
- return JSONResponse(status_code=404, content="Session not found.")
548
-
549
- agent_session_dict = agent_session.to_dict()
550
- if agent_session.memory is not None:
551
- runs = agent_session.memory.get("runs")
552
- if runs is not None:
553
- first_run = runs[0]
554
- if "content" in first_run or first_run.get("is_paused", False) or first_run.get("event") == "RunPaused":
555
- agent_session_dict["runs"] = []
556
- for run in runs:
557
- first_user_message = None
558
- for msg in run.get("messages", []):
559
- if msg.get("role") == "user" and msg.get("from_history", False) is False:
560
- first_user_message = msg
561
- break
562
- # Remove the memory from the response
563
- run.pop("memory", None)
564
- agent_session_dict["runs"].append(
565
- {
566
- "message": first_user_message,
567
- "response": run,
568
- }
569
- )
570
-
571
- return agent_session_dict
572
-
573
- @playground_router.post("/agents/{agent_id}/sessions/{session_id}/rename")
574
- def rename_agent_session(agent_id: str, session_id: str, body: AgentRenameRequest):
575
- agent = get_agent_by_id(agent_id, agents)
576
- if agent is None:
577
- return JSONResponse(status_code=404, content=f"couldn't find agent with {agent_id}")
578
-
579
- if agent.storage is None:
580
- return JSONResponse(status_code=404, content="Agent does not have storage enabled.")
581
-
582
- all_agent_sessions: List[AgentSession] = agent.storage.get_all_sessions(user_id=body.user_id) # type: ignore
583
- for session in all_agent_sessions:
584
- if session.session_id == session_id:
585
- agent.rename_session(body.name, session_id=session_id)
586
- return JSONResponse(content={"message": f"successfully renamed agent {agent.name}"})
587
-
588
- return JSONResponse(status_code=404, content="Session not found.")
589
-
590
- @playground_router.delete("/agents/{agent_id}/sessions/{session_id}")
591
- def delete_agent_session(agent_id: str, session_id: str, user_id: Optional[str] = Query(None, min_length=1)):
592
- agent = get_agent_by_id(agent_id, agents)
593
- if agent is None:
594
- return JSONResponse(status_code=404, content="Agent not found.")
595
-
596
- if agent.storage is None:
597
- return JSONResponse(status_code=404, content="Agent does not have storage enabled.")
598
-
599
- all_agent_sessions: List[AgentSession] = agent.storage.get_all_sessions(user_id=user_id, entity_id=agent_id) # type: ignore
600
- for session in all_agent_sessions:
601
- if session.session_id == session_id:
602
- agent.delete_session(session_id)
603
- return JSONResponse(content={"message": f"successfully deleted agent {agent.name}"})
604
-
605
- return JSONResponse(status_code=404, content="Session not found.")
606
-
607
- @playground_router.get("/agents/{agent_id}/memories")
608
- async def get_agent_memories(agent_id: str, user_id: str = Query(..., min_length=1)):
609
- agent = get_agent_by_id(agent_id, agents)
610
- if agent is None:
611
- return JSONResponse(status_code=404, content="Agent not found.")
612
-
613
- if agent.memory is None:
614
- return JSONResponse(status_code=404, content="Agent does not have memory enabled.")
615
-
616
- if isinstance(agent.memory, Memory):
617
- memories = agent.memory.get_user_memories(user_id=user_id)
618
- return [
619
- MemoryResponse(memory=memory.memory, topics=memory.topics, last_updated=memory.last_updated)
620
- for memory in memories
621
- ]
622
- else:
623
- return []
624
-
625
- @playground_router.get("/workflows", response_model=List[WorkflowsGetResponse])
626
- def get_workflows():
627
- if workflows is None:
628
- return []
629
-
630
- return [
631
- WorkflowsGetResponse(
632
- workflow_id=str(workflow.workflow_id),
633
- name=workflow.name,
634
- description=workflow.description,
635
- )
636
- for workflow in workflows
637
- ]
638
-
639
- @playground_router.get("/workflows/{workflow_id}", response_model=WorkflowGetResponse)
640
- def get_workflow(workflow_id: str):
641
- workflow = get_workflow_by_id(workflow_id, workflows)
642
- if workflow is None:
643
- raise HTTPException(status_code=404, detail="Workflow not found")
644
-
645
- if isinstance(workflow, Workflow):
646
- return WorkflowGetResponse(
647
- workflow_id=workflow.workflow_id,
648
- name=workflow.name,
649
- description=workflow.description,
650
- parameters=workflow._run_parameters or {},
651
- storage=workflow.storage.__class__.__name__ if workflow.storage else None,
652
- )
653
- else:
654
- return WorkflowGetResponse(
655
- workflow_id=workflow.workflow_id,
656
- name=workflow.name,
657
- description=workflow.description,
658
- parameters=workflow.run_parameters,
659
- storage=workflow.storage.__class__.__name__ if workflow.storage else None,
660
- )
661
-
662
- @playground_router.post("/workflows/{workflow_id}/runs")
663
- def create_workflow_run(workflow_id: str, body: WorkflowRunRequest):
664
- # Retrieve the workflow by ID
665
- workflow = get_workflow_by_id(workflow_id, workflows)
666
- if workflow is None:
667
- raise HTTPException(status_code=404, detail="Workflow not found")
668
-
669
- # Create a new instance of this workflow
670
- if isinstance(workflow, Workflow):
671
- new_workflow_instance = workflow.deep_copy(
672
- update={"workflow_id": workflow_id, "session_id": body.session_id}
673
- )
674
- new_workflow_instance.user_id = body.user_id
675
- new_workflow_instance.session_name = None
676
-
677
- # Return based on the response type
678
- try:
679
- if new_workflow_instance._run_return_type == "RunResponse":
680
- # Return as a normal response
681
- return new_workflow_instance.run(**body.input)
682
- else:
683
- # Return as a streaming response
684
- return StreamingResponse(
685
- (result.to_json() for result in new_workflow_instance.run(**body.input)),
686
- media_type="text/event-stream",
687
- headers={
688
- "Access-Control-Allow-Origin": "*",
689
- "Access-Control-Allow-Methods": "POST, OPTIONS",
690
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
691
- },
692
- )
693
- except Exception as e:
694
- # Handle unexpected runtime errors
695
- raise HTTPException(status_code=500, detail=f"Error running workflow: {str(e)}")
696
- else:
697
- # Return based on the response type
698
- try:
699
- if body.stream:
700
- # Return as a streaming response
701
- return StreamingResponse(
702
- workflow_response_streamer(workflow, body),
703
- media_type="text/event-stream",
704
- headers={
705
- "Access-Control-Allow-Origin": "*",
706
- "Access-Control-Allow-Methods": "POST, OPTIONS",
707
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
708
- },
709
- )
710
- else:
711
- # Return as a normal response
712
- return workflow.arun(**body.input, session_id=body.session_id or str(uuid4()), user_id=body.user_id)
713
- except Exception as e:
714
- # Handle unexpected runtime errors
715
- raise HTTPException(status_code=500, detail=f"Error running workflow: {str(e)}")
716
-
717
- @playground_router.get("/workflows/{workflow_id}/sessions")
718
- def get_all_workflow_sessions(workflow_id: str, user_id: Optional[str] = Query(None, min_length=1)):
719
- # Retrieve the workflow by ID
720
- workflow = get_workflow_by_id(workflow_id, workflows)
721
- if not workflow:
722
- raise HTTPException(status_code=404, detail="Workflow not found")
723
-
724
- # Ensure storage is enabled for the workflow
725
- if not workflow.storage:
726
- raise HTTPException(status_code=404, detail="Workflow does not have storage enabled")
727
-
728
- # Retrieve all sessions for the given workflow and user
729
- try:
730
- all_workflow_sessions: List[WorkflowSession] = workflow.storage.get_all_sessions(
731
- user_id=user_id, entity_id=workflow_id
732
- ) # type: ignore
733
- except Exception as e:
734
- raise HTTPException(status_code=500, detail=f"Error retrieving sessions: {str(e)}")
735
-
736
- # Return the sessions
737
- workflow_sessions: List[WorkflowSessionResponse] = []
738
- for session in all_workflow_sessions:
739
- title = get_session_title_from_workflow_session(session)
740
- workflow_sessions.append(
741
- {
742
- "title": title,
743
- "session_id": session.session_id,
744
- "session_name": session.session_data.get("session_name") if session.session_data else None,
745
- "created_at": session.created_at,
746
- } # type: ignore
747
- )
748
- return workflow_sessions
749
-
750
- @playground_router.get("/workflows/{workflow_id}/sessions/{session_id}", response_model=WorkflowSession)
751
- def get_workflow_session(workflow_id: str, session_id: str, user_id: Optional[str] = Query(None, min_length=1)):
752
- # Retrieve the workflow by ID
753
- workflow = get_workflow_by_id(workflow_id, workflows)
754
- if not workflow:
755
- raise HTTPException(status_code=404, detail="Workflow not found")
756
-
757
- # Ensure storage is enabled for the workflow
758
- if not workflow.storage:
759
- raise HTTPException(status_code=404, detail="Workflow does not have storage enabled")
760
-
761
- # Retrieve the specific session
762
- try:
763
- workflow_session: Optional[WorkflowSession] = workflow.storage.read(session_id, user_id) # type: ignore
764
- except Exception as e:
765
- raise HTTPException(status_code=500, detail=f"Error retrieving session: {str(e)}")
766
-
767
- if not workflow_session:
768
- raise HTTPException(status_code=404, detail="Session not found")
769
-
770
- workflow_session_dict = workflow_session.to_dict()
771
- if "memory" not in workflow_session_dict:
772
- workflow_session_dict["memory"] = {"runs": workflow_session_dict.pop("runs", [])}
773
-
774
- return JSONResponse(content=workflow_session_dict)
775
-
776
- @playground_router.post("/workflows/{workflow_id}/sessions/{session_id}/rename")
777
- def rename_workflow_session(
778
- workflow_id: str,
779
- session_id: str,
780
- body: WorkflowRenameRequest,
781
- ):
782
- workflow = get_workflow_by_id(workflow_id, workflows)
783
- if workflow is None:
784
- raise HTTPException(status_code=404, detail="Workflow not found")
785
-
786
- workflow.session_id = session_id
787
- workflow.rename_session(body.name)
788
- return JSONResponse(content={"message": f"successfully renamed workflow {workflow.name}"})
789
-
790
- @playground_router.delete("/workflows/{workflow_id}/sessions/{session_id}")
791
- def delete_workflow_session(workflow_id: str, session_id: str):
792
- workflow = get_workflow_by_id(workflow_id, workflows)
793
- if workflow is None:
794
- raise HTTPException(status_code=404, detail="Workflow not found")
795
-
796
- workflow.delete_session(session_id)
797
- return JSONResponse(content={"message": f"successfully deleted workflow {workflow.name}"})
798
-
799
- @playground_router.get("/teams")
800
- def get_teams():
801
- if teams is None:
802
- return []
803
-
804
- return [TeamGetResponse.from_team(team) for team in teams]
805
-
806
- @playground_router.get("/teams/{team_id}")
807
- def get_team(team_id: str):
808
- team = get_team_by_id(team_id, teams)
809
- if team is None:
810
- raise HTTPException(status_code=404, detail="Team not found")
811
-
812
- return TeamGetResponse.from_team(team)
813
-
814
- @playground_router.post("/teams/{team_id}/runs")
815
- def create_team_run(
816
- team_id: str,
817
- message: str = Form(...),
818
- stream: bool = Form(True),
819
- monitor: bool = Form(True),
820
- session_id: Optional[str] = Form(None),
821
- user_id: Optional[str] = Form(None),
822
- files: Optional[List[UploadFile]] = File(None),
823
- ):
824
- logger.debug(f"Creating team run: {message} {session_id} {monitor} {user_id} {team_id} {files}")
825
- team = get_team_by_id(team_id, teams)
826
- if team is None:
827
- raise HTTPException(status_code=404, detail="Team not found")
828
-
829
- if session_id is not None and session_id != "":
830
- logger.debug(f"Continuing session: {session_id}")
831
- else:
832
- logger.debug("Creating new session")
833
- session_id = str(uuid4())
834
-
835
- if monitor:
836
- team.monitoring = True
837
- else:
838
- team.monitoring = False
839
-
840
- base64_images: List[Image] = []
841
- base64_audios: List[Audio] = []
842
- base64_videos: List[Video] = []
843
- document_files: List[FileMedia] = []
844
-
845
- if files:
846
- for file in files:
847
- if file.content_type in ["image/png", "image/jpeg", "image/jpg", "image/webp"]:
848
- try:
849
- base64_image = process_image(file)
850
- base64_images.append(base64_image)
851
- except Exception as e:
852
- logger.error(f"Error processing image {file.filename}: {e}")
853
- continue
854
- elif file.content_type in ["audio/wav", "audio/mp3", "audio/mpeg"]:
855
- try:
856
- base64_audio = process_audio(file)
857
- base64_audios.append(base64_audio)
858
- except Exception as e:
859
- logger.error(f"Error processing audio {file.filename}: {e}")
860
- continue
861
- elif file.content_type in [
862
- "video/x-flv",
863
- "video/quicktime",
864
- "video/mpeg",
865
- "video/mpegs",
866
- "video/mpgs",
867
- "video/mpg",
868
- "video/mpg",
869
- "video/mp4",
870
- "video/webm",
871
- "video/wmv",
872
- "video/3gpp",
873
- ]:
874
- try:
875
- base64_video = process_video(file)
876
- base64_videos.append(base64_video)
877
- except Exception as e:
878
- logger.error(f"Error processing video {file.filename}: {e}")
879
- continue
880
- elif file.content_type in [
881
- "application/pdf",
882
- "text/csv",
883
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
884
- "text/plain",
885
- "application/json",
886
- ]:
887
- document_file = process_document(file)
888
- if document_file is not None:
889
- document_files.append(document_file)
890
- else:
891
- raise HTTPException(status_code=400, detail="Unsupported file type")
892
-
893
- if stream:
894
- return StreamingResponse(
895
- team_chat_response_streamer(
896
- team,
897
- message,
898
- session_id=session_id,
899
- user_id=user_id,
900
- images=base64_images if base64_images else None,
901
- audio=base64_audios if base64_audios else None,
902
- videos=base64_videos if base64_videos else None,
903
- files=document_files if document_files else None,
904
- ),
905
- media_type="text/event-stream",
906
- )
907
- else:
908
- run_response = team.run(
909
- message=message,
910
- session_id=session_id,
911
- user_id=user_id,
912
- images=base64_images if base64_images else None,
913
- audio=base64_audios if base64_audios else None,
914
- videos=base64_videos if base64_videos else None,
915
- files=document_files if document_files else None,
916
- stream=False,
917
- )
918
- return run_response.to_dict()
919
-
920
- @playground_router.get("/teams/{team_id}/sessions", response_model=List[TeamSessionResponse])
921
- def get_all_team_sessions(team_id: str, user_id: Optional[str] = Query(None, min_length=1)):
922
- team = get_team_by_id(team_id, teams)
923
- if team is None:
924
- raise HTTPException(status_code=404, detail="Team not found")
925
-
926
- if team.storage is None:
927
- raise HTTPException(status_code=404, detail="Team does not have storage enabled")
928
-
929
- try:
930
- all_team_sessions: List[TeamSession] = team.storage.get_all_sessions(user_id=user_id, entity_id=team_id) # type: ignore
931
- except Exception as e:
932
- raise HTTPException(status_code=500, detail=f"Error retrieving sessions: {str(e)}")
933
-
934
- team_sessions: List[TeamSessionResponse] = []
935
- for session in all_team_sessions:
936
- title = get_session_title_from_team_session(session)
937
- team_sessions.append(
938
- TeamSessionResponse(
939
- title=title,
940
- session_id=session.session_id,
941
- session_name=session.session_data.get("session_name") if session.session_data else None,
942
- created_at=session.created_at,
943
- )
944
- )
945
- return team_sessions
946
-
947
- @playground_router.get("/teams/{team_id}/sessions/{session_id}")
948
- def get_team_session(team_id: str, session_id: str, user_id: Optional[str] = Query(None, min_length=1)):
949
- team = get_team_by_id(team_id, teams)
950
- if team is None:
951
- raise HTTPException(status_code=404, detail="Team not found")
952
-
953
- if team.storage is None:
954
- raise HTTPException(status_code=404, detail="Team does not have storage enabled")
955
-
956
- try:
957
- team_session: Optional[TeamSession] = team.storage.read(session_id, user_id) # type: ignore
958
- except Exception as e:
959
- raise HTTPException(status_code=500, detail=f"Error retrieving session: {str(e)}")
960
-
961
- if not team_session:
962
- raise HTTPException(status_code=404, detail="Session not found")
963
-
964
- team_session_dict = team_session.to_dict()
965
- if team_session.memory is not None:
966
- runs = team_session.memory.get("runs")
967
- if runs is not None:
968
- first_run = runs[0]
969
- if "content" in first_run or first_run.get("is_paused", False) or first_run.get("event") == "RunPaused":
970
- team_session_dict["runs"] = []
971
- for run in runs:
972
- # We skip runs that are not from the parent team
973
- if run.get("team_session_id") is not None and run.get("team_session_id") == session_id:
974
- continue
975
- first_user_message = None
976
- for msg in run.get("messages", []):
977
- if msg.get("role") == "user" and msg.get("from_history", False) is False:
978
- first_user_message = msg
979
- break
980
- # Remove the memory from the response
981
- run.pop("memory", None)
982
- team_session_dict["runs"].append(
983
- {
984
- "message": first_user_message,
985
- "response": run,
986
- }
987
- )
988
- return team_session_dict
989
-
990
- @playground_router.post("/teams/{team_id}/sessions/{session_id}/rename")
991
- def rename_team_session(team_id: str, session_id: str, body: TeamRenameRequest):
992
- team = get_team_by_id(team_id, teams)
993
- if team is None:
994
- raise HTTPException(status_code=404, detail="Team not found")
995
-
996
- if team.storage is None:
997
- raise HTTPException(status_code=404, detail="Team does not have storage enabled")
998
-
999
- all_team_sessions: List[TeamSession] = team.storage.get_all_sessions(user_id=body.user_id, entity_id=team_id) # type: ignore
1000
- for session in all_team_sessions:
1001
- if session.session_id == session_id:
1002
- team.rename_session(body.name, session_id=session_id)
1003
- return JSONResponse(content={"message": f"successfully renamed team session {body.name}"})
1004
-
1005
- raise HTTPException(status_code=404, detail="Session not found")
1006
-
1007
- @playground_router.delete("/teams/{team_id}/sessions/{session_id}")
1008
- def delete_team_session(team_id: str, session_id: str, user_id: Optional[str] = Query(None, min_length=1)):
1009
- team = get_team_by_id(team_id, teams)
1010
- if team is None:
1011
- raise HTTPException(status_code=404, detail="Team not found")
1012
-
1013
- if team.storage is None:
1014
- raise HTTPException(status_code=404, detail="Team does not have storage enabled")
1015
-
1016
- all_team_sessions: List[TeamSession] = team.storage.get_all_sessions(user_id=user_id, entity_id=team_id) # type: ignore
1017
- for session in all_team_sessions:
1018
- if session.session_id == session_id:
1019
- team.delete_session(session_id)
1020
- return JSONResponse(content={"message": f"successfully deleted team session {session_id}"})
1021
-
1022
- raise HTTPException(status_code=404, detail="Session not found")
1023
-
1024
- @playground_router.get("/team/{team_id}/memories")
1025
- async def get_team_memories(team_id: str, user_id: str = Query(..., min_length=1)):
1026
- team = get_team_by_id(team_id, teams)
1027
- if team is None:
1028
- return JSONResponse(status_code=404, content="Teem not found.")
1029
-
1030
- if team.memory is None:
1031
- return JSONResponse(status_code=404, content="Team does not have memory enabled.")
1032
-
1033
- if isinstance(team.memory, Memory):
1034
- memories = team.memory.get_user_memories(user_id=user_id)
1035
- return [
1036
- MemoryResponse(memory=memory.memory, topics=memory.topics, last_updated=memory.last_updated)
1037
- for memory in memories
1038
- ]
1039
- else:
1040
- return []
1041
-
1042
- return playground_router