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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/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 +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  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 +38 -144
  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 +84 -46
  158. agno/models/openai/chat.py +121 -23
  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 +14 -8
  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 +393 -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 +65 -28
  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 +33 -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 +30 -0
  184. agno/os/router.py +843 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +204 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +413 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +179 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +58 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +2961 -4253
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +42 -22
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +18 -13
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,269 @@
1
+ import json
2
+ import time
3
+ from datetime import date, datetime, timedelta, timezone
4
+ from typing import Any, Dict, List, Optional
5
+ from uuid import uuid4
6
+
7
+ from agno.db.sqlite.schemas import get_table_schema_definition
8
+ from agno.utils.log import log_debug, log_error, log_warning
9
+
10
+ try:
11
+ from sqlalchemy import Table
12
+ from sqlalchemy.dialects import sqlite
13
+ from sqlalchemy.engine import Engine
14
+ from sqlalchemy.inspection import inspect
15
+ from sqlalchemy.orm import Session
16
+ from sqlalchemy.sql.expression import text
17
+ except ImportError:
18
+ raise ImportError("`sqlalchemy` not installed. Please install it using `pip install sqlalchemy`")
19
+
20
+
21
+ # -- DB util methods --
22
+
23
+
24
+ def apply_sorting(stmt, table: Table, sort_by: Optional[str] = None, sort_order: Optional[str] = None):
25
+ """Apply sorting to the given SQLAlchemy statement.
26
+ Args:
27
+ stmt: The SQLAlchemy statement to modify
28
+ table: The table being queried
29
+ sort_by: The field to sort by
30
+ sort_order: The sort order ('asc' or 'desc')
31
+ Returns:
32
+ The modified statement with sorting applied
33
+ """
34
+ if sort_by is None:
35
+ return stmt
36
+ if not hasattr(table.c, sort_by):
37
+ log_debug(f"Invalid sort field: '{sort_by}'. Will not apply any sorting.")
38
+ return stmt
39
+
40
+ # Apply the given sorting
41
+ sort_column = getattr(table.c, sort_by)
42
+ if sort_order and sort_order == "asc":
43
+ return stmt.order_by(sort_column.asc())
44
+ else:
45
+ return stmt.order_by(sort_column.desc())
46
+
47
+
48
+ def is_table_available(session: Session, table_name: str, db_schema: Optional[str] = None) -> bool:
49
+ """
50
+ Check if a table with the given name exists.
51
+ Note: db_schema parameter is ignored in SQLite but kept for API compatibility.
52
+ Returns:
53
+ bool: True if the table exists, False otherwise.
54
+ """
55
+ try:
56
+ # SQLite uses sqlite_master instead of information_schema
57
+ exists_query = text("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = :table")
58
+ exists = session.execute(exists_query, {"table": table_name}).scalar() is not None
59
+ if not exists:
60
+ log_debug(f"Table {table_name} {'exists' if exists else 'does not exist'}")
61
+ return exists
62
+ except Exception as e:
63
+ log_error(f"Error checking if table exists: {e}")
64
+ return False
65
+
66
+
67
+ def is_valid_table(db_engine: Engine, table_name: str, table_type: str, db_schema: Optional[str] = None) -> bool:
68
+ """
69
+ Check if the existing table has the expected column names.
70
+ Note: db_schema parameter is ignored in SQLite but kept for API compatibility.
71
+ Args:
72
+ db_engine (Engine): Database engine
73
+ table_name (str): Name of the table to validate
74
+ table_type (str): Type of table to get expected schema
75
+ db_schema (Optional[str]): Database schema name (ignored in SQLite)
76
+ Returns:
77
+ bool: True if table has all expected columns, False otherwise
78
+ """
79
+ try:
80
+ expected_table_schema = get_table_schema_definition(table_type)
81
+ expected_columns = {col_name for col_name in expected_table_schema.keys() if not col_name.startswith("_")}
82
+
83
+ # Get existing columns (no schema parameter for SQLite)
84
+ inspector = inspect(db_engine)
85
+ existing_columns_info = inspector.get_columns(table_name) # No schema parameter
86
+ existing_columns = set(col["name"] for col in existing_columns_info)
87
+
88
+ # Check if all expected columns exist
89
+ missing_columns = expected_columns - existing_columns
90
+ if missing_columns:
91
+ log_warning(f"Missing columns {missing_columns} in table {table_name}")
92
+ return False
93
+
94
+ log_debug(f"Table {table_name} has all expected columns")
95
+ return True
96
+ except Exception as e:
97
+ log_error(f"Error validating table schema for {table_name}: {e}")
98
+ return False
99
+
100
+
101
+ # -- Metrics util methods --
102
+
103
+
104
+ def bulk_upsert_metrics(session: Session, table: Table, metrics_records: list[dict]) -> list[dict]:
105
+ """Bulk upsert metrics into the database.
106
+
107
+ Args:
108
+ table (Table): The table to upsert into.
109
+ metrics_records (list[dict]): The metrics records to upsert.
110
+
111
+ Returns:
112
+ list[dict]: The upserted metrics records.
113
+ """
114
+ if not metrics_records:
115
+ return []
116
+
117
+ results = []
118
+ stmt = sqlite.insert(table)
119
+
120
+ # Columns to update in case of conflict
121
+ update_columns = {
122
+ col.name: stmt.excluded[col.name]
123
+ for col in table.columns
124
+ if col.name not in ["id", "date", "created_at", "aggregation_period"]
125
+ }
126
+
127
+ stmt = stmt.on_conflict_do_update(index_elements=["date", "aggregation_period"], set_=update_columns).returning( # type: ignore
128
+ table
129
+ )
130
+ result = session.execute(stmt, metrics_records)
131
+ results = [row._mapping for row in result.fetchall()]
132
+ session.commit()
133
+
134
+ return results # type: ignore
135
+
136
+
137
+ def calculate_date_metrics(date_to_process: date, sessions_data: dict) -> dict:
138
+ """Calculate metrics for the given single date.
139
+
140
+ Args:
141
+ date_to_process (date): The date to calculate metrics for.
142
+ sessions_data (dict): The sessions data to calculate metrics for.
143
+
144
+ Returns:
145
+ dict: The calculated metrics.
146
+ """
147
+ metrics = {
148
+ "users_count": 0,
149
+ "agent_sessions_count": 0,
150
+ "team_sessions_count": 0,
151
+ "workflow_sessions_count": 0,
152
+ "agent_runs_count": 0,
153
+ "team_runs_count": 0,
154
+ "workflow_runs_count": 0,
155
+ }
156
+ token_metrics = {
157
+ "input_tokens": 0,
158
+ "output_tokens": 0,
159
+ "total_tokens": 0,
160
+ "audio_total_tokens": 0,
161
+ "audio_input_tokens": 0,
162
+ "audio_output_tokens": 0,
163
+ "cache_read_tokens": 0,
164
+ "cache_write_tokens": 0,
165
+ "reasoning_tokens": 0,
166
+ }
167
+ model_counts: Dict[str, int] = {}
168
+
169
+ session_types = [
170
+ ("agent", "agent_sessions_count", "agent_runs_count"),
171
+ ("team", "team_sessions_count", "team_runs_count"),
172
+ ("workflow", "workflow_sessions_count", "workflow_runs_count"),
173
+ ]
174
+ all_user_ids = set()
175
+
176
+ for session_type, sessions_count_key, runs_count_key in session_types:
177
+ sessions = sessions_data.get(session_type, [])
178
+ metrics[sessions_count_key] = len(sessions)
179
+
180
+ for session in sessions:
181
+ if session.get("user_id"):
182
+ all_user_ids.add(session["user_id"])
183
+ metrics[runs_count_key] += len(session.get("runs", []))
184
+ if runs := session.get("runs", []):
185
+ runs = json.loads(runs)
186
+ for run in runs:
187
+ if model_id := run.get("model"):
188
+ model_provider = run.get("model_provider", "")
189
+ model_counts[f"{model_id}:{model_provider}"] = (
190
+ model_counts.get(f"{model_id}:{model_provider}", 0) + 1
191
+ )
192
+
193
+ session_data = json.loads(session.get("session_data", {}))
194
+ session_metrics = session_data.get("session_metrics", {})
195
+ for field in token_metrics:
196
+ token_metrics[field] += session_metrics.get(field, 0)
197
+
198
+ model_metrics = []
199
+ for model, count in model_counts.items():
200
+ model_id, model_provider = model.split(":")
201
+ model_metrics.append({"model_id": model_id, "model_provider": model_provider, "count": count})
202
+
203
+ metrics["users_count"] = len(all_user_ids)
204
+ current_time = int(time.time())
205
+
206
+ return {
207
+ "id": str(uuid4()),
208
+ "date": date_to_process,
209
+ "completed": date_to_process < datetime.now(timezone.utc).date(),
210
+ "token_metrics": token_metrics,
211
+ "model_metrics": model_metrics,
212
+ "created_at": current_time,
213
+ "updated_at": current_time,
214
+ "aggregation_period": "daily",
215
+ **metrics,
216
+ }
217
+
218
+
219
+ def fetch_all_sessions_data(
220
+ sessions: List[Dict[str, Any]], dates_to_process: list[date], start_timestamp: int
221
+ ) -> Optional[dict]:
222
+ """Return all session data for the given dates, for all session types.
223
+
224
+ Args:
225
+ dates_to_process (list[date]): The dates to fetch session data for.
226
+
227
+ Returns:
228
+ dict: A dictionary with dates as keys and session data as values, for all session types.
229
+
230
+ Example:
231
+ {
232
+ "2000-01-01": {
233
+ "agent": [<session1>, <session2>, ...],
234
+ "team": [...],
235
+ "workflow": [...],
236
+ }
237
+ }
238
+ """
239
+ if not dates_to_process:
240
+ return None
241
+
242
+ all_sessions_data: Dict[str, Dict[str, List[Dict[str, Any]]]] = {
243
+ date_to_process.isoformat(): {"agent": [], "team": [], "workflow": []} for date_to_process in dates_to_process
244
+ }
245
+
246
+ for session in sessions:
247
+ session_date = (
248
+ datetime.fromtimestamp(session.get("created_at", start_timestamp), tz=timezone.utc).date().isoformat()
249
+ )
250
+ if session_date in all_sessions_data:
251
+ all_sessions_data[session_date][session["session_type"]].append(session)
252
+
253
+ return all_sessions_data
254
+
255
+
256
+ def get_dates_to_calculate_metrics_for(starting_date: date) -> list[date]:
257
+ """Return the list of dates to calculate metrics for.
258
+
259
+ Args:
260
+ starting_date (date): The starting date to calculate metrics for.
261
+
262
+ Returns:
263
+ list[date]: The list of dates to calculate metrics for.
264
+ """
265
+ today = datetime.now(timezone.utc).date()
266
+ days_diff = (today - starting_date).days + 1
267
+ if days_diff <= 0:
268
+ return []
269
+ return [starting_date + timedelta(days=x) for x in range(days_diff)]
agno/db/utils.py ADDED
@@ -0,0 +1,88 @@
1
+ """Logic shared across different database implementations"""
2
+
3
+ import json
4
+ from datetime import date, datetime
5
+ from uuid import UUID
6
+
7
+ from agno.db.base import SessionType
8
+ from agno.models.message import Message
9
+ from agno.models.metrics import Metrics
10
+
11
+
12
+ class CustomJSONEncoder(json.JSONEncoder):
13
+ """Custom encoder to handle non JSON serializable types."""
14
+
15
+ def default(self, obj):
16
+ if isinstance(obj, UUID):
17
+ return str(obj)
18
+ elif isinstance(obj, (date, datetime)):
19
+ return obj.isoformat()
20
+ elif isinstance(obj, Message):
21
+ return obj.to_dict()
22
+ elif isinstance(obj, Metrics):
23
+ return obj.to_dict()
24
+
25
+ return super().default(obj)
26
+
27
+
28
+ def serialize_session_json_fields(session: dict) -> dict:
29
+ """Serialize all JSON fields in the given Session dictionary.
30
+
31
+ Args:
32
+ data (dict): The dictionary to serialize JSON fields in.
33
+
34
+ Returns:
35
+ dict: The dictionary with JSON fields serialized.
36
+ """
37
+ if session.get("session_data") is not None:
38
+ session["session_data"] = json.dumps(session["session_data"])
39
+ if session.get("agent_data") is not None:
40
+ session["agent_data"] = json.dumps(session["agent_data"])
41
+ if session.get("team_data") is not None:
42
+ session["team_data"] = json.dumps(session["team_data"])
43
+ if session.get("workflow_data") is not None:
44
+ session["workflow_data"] = json.dumps(session["workflow_data"])
45
+ if session.get("metadata") is not None:
46
+ session["metadata"] = json.dumps(session["metadata"])
47
+ if session.get("chat_history") is not None:
48
+ session["chat_history"] = json.dumps(session["chat_history"])
49
+ if session.get("summary") is not None:
50
+ session["summary"] = json.dumps(session["summary"], cls=CustomJSONEncoder)
51
+ if session.get("runs") is not None:
52
+ session["runs"] = json.dumps(session["runs"], cls=CustomJSONEncoder)
53
+
54
+ return session
55
+
56
+
57
+ def deserialize_session_json_fields(session: dict) -> dict:
58
+ """Deserialize all JSON fields in the given Session dictionary.
59
+
60
+ Args:
61
+ session (dict): The dictionary to deserialize.
62
+
63
+ Returns:
64
+ dict: The dictionary with JSON fields deserialized.
65
+ """
66
+ if session.get("agent_data") is not None:
67
+ session["agent_data"] = json.loads(session["agent_data"])
68
+ if session.get("team_data") is not None:
69
+ session["team_data"] = json.loads(session["team_data"])
70
+ if session.get("workflow_data") is not None:
71
+ session["workflow_data"] = json.loads(session["workflow_data"])
72
+ if session.get("metadata") is not None:
73
+ session["metadata"] = json.loads(session["metadata"])
74
+ if session.get("chat_history") is not None:
75
+ session["chat_history"] = json.loads(session["chat_history"])
76
+ if session.get("summary") is not None:
77
+ session["summary"] = json.loads(session["summary"])
78
+ if session.get("session_data") is not None and isinstance(session["session_data"], str):
79
+ session["session_data"] = json.loads(session["session_data"])
80
+ if session.get("runs") is not None:
81
+ if session["session_type"] == SessionType.AGENT.value:
82
+ session["runs"] = json.loads(session["runs"])
83
+ if session["session_type"] == SessionType.TEAM.value:
84
+ session["runs"] = json.loads(session["runs"])
85
+ if session["session_type"] == SessionType.WORKFLOW.value:
86
+ session["runs"] = json.loads(session["runs"])
87
+
88
+ return session
agno/eval/__init__.py CHANGED
@@ -0,0 +1,14 @@
1
+ from agno.eval.accuracy import AccuracyAgentResponse, AccuracyEval, AccuracyEvaluation, AccuracyResult
2
+ from agno.eval.performance import PerformanceEval, PerformanceResult
3
+ from agno.eval.reliability import ReliabilityEval, ReliabilityResult
4
+
5
+ __all__ = [
6
+ "AccuracyAgentResponse",
7
+ "AccuracyEvaluation",
8
+ "AccuracyResult",
9
+ "AccuracyEval",
10
+ "PerformanceEval",
11
+ "PerformanceResult",
12
+ "ReliabilityEval",
13
+ "ReliabilityResult",
14
+ ]
agno/eval/accuracy.py CHANGED
@@ -1,14 +1,15 @@
1
1
  from dataclasses import asdict, dataclass, field
2
2
  from os import getenv
3
3
  from textwrap import dedent
4
- from typing import TYPE_CHECKING, Callable, List, Optional, Union
4
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
5
5
  from uuid import uuid4
6
6
 
7
7
  from pydantic import BaseModel, Field
8
8
 
9
9
  from agno.agent import Agent
10
- from agno.api.schemas.evals import EvalType
11
- from agno.eval.utils import async_log_eval_run, log_eval_run, store_result_in_file
10
+ from agno.db.base import BaseDb
11
+ from agno.db.schemas.evals import EvalType
12
+ from agno.eval.utils import async_log_eval, log_eval_run, store_result_in_file
12
13
  from agno.exceptions import EvalError
13
14
  from agno.models.base import Model
14
15
  from agno.team.team import Team
@@ -167,8 +168,13 @@ class AccuracyEval:
167
168
  file_path_to_save_results: Optional[str] = None
168
169
  # Enable debug logs
169
170
  debug_mode: bool = getenv("AGNO_DEBUG", "false").lower() == "true"
170
- # Log the results to the Agno platform. On by default.
171
- monitoring: bool = getenv("AGNO_MONITOR", "true").lower() == "true"
171
+ # The database to store Evaluation results
172
+ db: Optional[BaseDb] = None
173
+
174
+ # Telemetry settings
175
+ # telemetry=True logs minimal telemetry for analytics
176
+ # This helps us improve our Evals and provide better support
177
+ telemetry: bool = True
172
178
 
173
179
  def get_evaluator_agent(self) -> Agent:
174
180
  """Return the evaluator agent. If not provided, build it based on the evaluator fields and default instructions."""
@@ -235,7 +241,7 @@ You are an expert judge tasked with comparing the quality of an AI Agent’s out
235
241
  {additional_guidelines}{additional_context}
236
242
  Remember: You must only compare the agent_output to the expected_output. The expected_output is correct as it was provided by the user.
237
243
  """,
238
- response_model=AccuracyAgentResponse,
244
+ output_schema=AccuracyAgentResponse,
239
245
  structured_outputs=True,
240
246
  )
241
247
 
@@ -344,9 +350,9 @@ Remember: You must only compare the agent_output to the expected_output. The exp
344
350
  live_log.update(status)
345
351
 
346
352
  if self.agent is not None:
347
- output = self.agent.run(message=eval_input).content
353
+ output = self.agent.run(input=eval_input).content
348
354
  elif self.team is not None:
349
- output = self.team.run(message=eval_input).content
355
+ output = self.team.run(input=eval_input).content
350
356
 
351
357
  if not output:
352
358
  logger.error(f"Failed to generate a valid answer on iteration {i + 1}: {output}")
@@ -398,22 +404,31 @@ Remember: You must only compare the agent_output to the expected_output. The exp
398
404
  if self.print_summary or print_summary:
399
405
  self.result.print_summary(console)
400
406
 
401
- # Log results to the Agno platform if requested
407
+ # Log results to the Agno DB if requested
402
408
  if self.agent is not None:
403
- agent_id = self.agent.agent_id
409
+ agent_id = self.agent.id
404
410
  team_id = None
405
411
  model_id = self.agent.model.id if self.agent.model is not None else None
406
412
  model_provider = self.agent.model.provider if self.agent.model is not None else None
407
- evaluated_entity_name = self.agent.name
413
+ evaluated_component_name = self.agent.name
408
414
  elif self.team is not None:
409
415
  agent_id = None
410
- team_id = self.team.team_id
416
+ team_id = self.team.id
411
417
  model_id = self.team.model.id if self.team.model is not None else None
412
418
  model_provider = self.team.model.provider if self.team.model is not None else None
413
- evaluated_entity_name = self.team.name
419
+ evaluated_component_name = self.team.name
420
+
421
+ if self.db:
422
+ log_eval_input = {
423
+ "additional_guidelines": self.additional_guidelines,
424
+ "additional_context": self.additional_context,
425
+ "num_iterations": self.num_iterations,
426
+ "expected_output": self.expected_output,
427
+ "input": self.input,
428
+ }
414
429
 
415
- if self.monitoring:
416
430
  log_eval_run(
431
+ db=self.db,
417
432
  run_id=self.eval_id, # type: ignore
418
433
  run_data=asdict(self.result),
419
434
  eval_type=EvalType.ACCURACY,
@@ -422,7 +437,19 @@ Remember: You must only compare the agent_output to the expected_output. The exp
422
437
  model_id=model_id,
423
438
  model_provider=model_provider,
424
439
  name=self.name if self.name is not None else None,
425
- evaluated_entity_name=evaluated_entity_name,
440
+ evaluated_component_name=evaluated_component_name,
441
+ eval_input=log_eval_input,
442
+ )
443
+
444
+ if self.telemetry:
445
+ from agno.api.evals import EvalRunCreate, create_eval_run_telemetry
446
+
447
+ create_eval_run_telemetry(
448
+ eval_run=EvalRunCreate(
449
+ run_id=self.eval_id,
450
+ eval_type=EvalType.ACCURACY,
451
+ data=self._get_telemetry_data(),
452
+ ),
426
453
  )
427
454
 
428
455
  logger.debug(f"*********** Evaluation {self.eval_id} Finished ***********")
@@ -464,10 +491,10 @@ Remember: You must only compare the agent_output to the expected_output. The exp
464
491
  live_log.update(status)
465
492
 
466
493
  if self.agent is not None:
467
- response = await self.agent.arun(message=eval_input)
494
+ response = await self.agent.arun(input=eval_input)
468
495
  output = response.content
469
496
  elif self.team is not None:
470
- response = await self.team.arun(message=eval_input)
497
+ response = await self.team.arun(input=eval_input) # type: ignore
471
498
  output = response.content
472
499
 
473
500
  if not output:
@@ -520,19 +547,48 @@ Remember: You must only compare the agent_output to the expected_output. The exp
520
547
  if self.print_summary or print_summary:
521
548
  self.result.print_summary(console)
522
549
 
523
- # Log results to the Agno platform if requested
524
- if self.monitoring:
525
- await async_log_eval_run(
550
+ if self.agent is not None:
551
+ agent_id = self.agent.id
552
+ team_id = None
553
+ model_id = self.agent.model.id if self.agent.model is not None else None
554
+ model_provider = self.agent.model.provider if self.agent.model is not None else None
555
+ evaluated_component_name = self.agent.name
556
+ elif self.team is not None:
557
+ agent_id = None
558
+ team_id = self.team.id
559
+ model_id = self.team.model.id if self.team.model is not None else None
560
+ model_provider = self.team.model.provider if self.team.model is not None else None
561
+ evaluated_component_name = self.team.name
562
+
563
+ # Log results to the Agno DB if requested
564
+ if self.db:
565
+ log_eval_input = {
566
+ "additional_guidelines": self.additional_guidelines,
567
+ "additional_context": self.additional_context,
568
+ "num_iterations": self.num_iterations,
569
+ "expected_output": self.expected_output,
570
+ "input": self.input,
571
+ }
572
+ await async_log_eval(
573
+ db=self.db,
526
574
  run_id=self.eval_id, # type: ignore
527
575
  run_data=asdict(self.result),
528
576
  eval_type=EvalType.ACCURACY,
529
- agent_id=self.agent.agent_id if self.agent is not None else None,
530
- model_id=self.agent.model.id if self.agent is not None and self.agent.model is not None else None,
531
- model_provider=self.agent.model.provider
532
- if self.agent is not None and self.agent.model is not None
533
- else None,
577
+ agent_id=agent_id,
578
+ model_id=model_id,
579
+ model_provider=model_provider,
534
580
  name=self.name if self.name is not None else None,
535
- evaluated_entity_name=self.agent.name if self.agent is not None else None,
581
+ evaluated_component_name=evaluated_component_name,
582
+ team_id=team_id,
583
+ workflow_id=None,
584
+ eval_input=log_eval_input,
585
+ )
586
+
587
+ if self.telemetry:
588
+ from agno.api.evals import EvalRunCreate, async_create_eval_run_telemetry
589
+
590
+ await async_create_eval_run_telemetry(
591
+ eval_run=EvalRunCreate(run_id=self.eval_id, eval_type=EvalType.ACCURACY),
536
592
  )
537
593
 
538
594
  logger.debug(f"*********** Evaluation {self.eval_id} Finished ***********")
@@ -596,28 +652,37 @@ Remember: You must only compare the agent_output to the expected_output. The exp
596
652
  eval_id=self.eval_id,
597
653
  result=self.result,
598
654
  )
599
- # Log results to the Agno platform if requested
600
- if self.monitoring:
655
+ # Log results to the Agno DB if requested
656
+ if self.db:
601
657
  if self.agent is not None:
602
- agent_id = self.agent.agent_id
658
+ agent_id = self.agent.id
603
659
  team_id = None
604
660
  model_id = self.agent.model.id if self.agent.model is not None else None
605
661
  model_provider = self.agent.model.provider if self.agent.model is not None else None
606
- evaluated_entity_name = self.agent.name
662
+ evaluated_component_name = self.agent.name
607
663
  elif self.team is not None:
608
664
  agent_id = None
609
- team_id = self.team.team_id
665
+ team_id = self.team.id
610
666
  model_id = self.team.model.id if self.team.model is not None else None
611
667
  model_provider = self.team.model.provider if self.team.model is not None else None
612
- evaluated_entity_name = self.team.name
668
+ evaluated_component_name = self.team.name
613
669
  else:
614
670
  agent_id = None
615
671
  team_id = None
616
672
  model_id = None
617
673
  model_provider = None
618
- evaluated_entity_name = None
674
+ evaluated_component_name = None
675
+
676
+ log_eval_input = {
677
+ "additional_guidelines": self.additional_guidelines,
678
+ "additional_context": self.additional_context,
679
+ "num_iterations": self.num_iterations,
680
+ "expected_output": self.expected_output,
681
+ "input": self.input,
682
+ }
619
683
 
620
684
  log_eval_run(
685
+ db=self.db,
621
686
  run_id=self.eval_id, # type: ignore
622
687
  run_data=asdict(self.result),
623
688
  eval_type=EvalType.ACCURACY,
@@ -626,7 +691,20 @@ Remember: You must only compare the agent_output to the expected_output. The exp
626
691
  team_id=team_id,
627
692
  model_id=model_id,
628
693
  model_provider=model_provider,
629
- evaluated_entity_name=evaluated_entity_name,
694
+ evaluated_component_name=evaluated_component_name,
695
+ workflow_id=None,
696
+ eval_input=log_eval_input,
697
+ )
698
+
699
+ if self.telemetry:
700
+ from agno.api.evals import EvalRunCreate, create_eval_run_telemetry
701
+
702
+ create_eval_run_telemetry(
703
+ eval_run=EvalRunCreate(
704
+ run_id=self.eval_id,
705
+ eval_type=EvalType.ACCURACY,
706
+ data=self._get_telemetry_data(),
707
+ ),
630
708
  )
631
709
 
632
710
  logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
@@ -690,22 +768,31 @@ Remember: You must only compare the agent_output to the expected_output. The exp
690
768
  eval_id=self.eval_id,
691
769
  result=self.result,
692
770
  )
693
- # Log results to the Agno platform if requested
694
- if self.monitoring:
771
+ # Log results to the Agno DB if requested
772
+ if self.db:
695
773
  if self.agent is not None:
696
- agent_id = self.agent.agent_id
774
+ agent_id = self.agent.id
697
775
  team_id = None
698
776
  model_id = self.agent.model.id if self.agent.model is not None else None
699
777
  model_provider = self.agent.model.provider if self.agent.model is not None else None
700
- evaluated_entity_name = self.agent.name
778
+ evaluated_component_name = self.agent.name
701
779
  elif self.team is not None:
702
780
  agent_id = None
703
- team_id = self.team.team_id
781
+ team_id = self.team.id
704
782
  model_id = self.team.model.id if self.team.model is not None else None
705
783
  model_provider = self.team.model.provider if self.team.model is not None else None
706
- evaluated_entity_name = self.team.name
707
-
708
- await async_log_eval_run(
784
+ evaluated_component_name = self.team.name
785
+
786
+ log_eval_input = {
787
+ "additional_guidelines": self.additional_guidelines,
788
+ "additional_context": self.additional_context,
789
+ "num_iterations": self.num_iterations,
790
+ "expected_output": self.expected_output,
791
+ "input": self.input,
792
+ }
793
+
794
+ await async_log_eval(
795
+ db=self.db,
709
796
  run_id=self.eval_id, # type: ignore
710
797
  run_data=asdict(self.result),
711
798
  eval_type=EvalType.ACCURACY,
@@ -714,8 +801,20 @@ Remember: You must only compare the agent_output to the expected_output. The exp
714
801
  team_id=team_id,
715
802
  model_id=model_id,
716
803
  model_provider=model_provider,
717
- evaluated_entity_name=evaluated_entity_name,
804
+ evaluated_component_name=evaluated_component_name,
805
+ workflow_id=None,
806
+ eval_input=log_eval_input,
718
807
  )
719
808
 
720
809
  logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
721
810
  return self.result
811
+
812
+ def _get_telemetry_data(self) -> Dict[str, Any]:
813
+ """Get the telemetry data for the evaluation"""
814
+ return {
815
+ "agent_id": self.agent.id if self.agent else None,
816
+ "team_id": self.team.id if self.team else None,
817
+ "model_id": self.agent.model.id if self.agent and self.agent.model else None,
818
+ "model_provider": self.agent.model.provider if self.agent and self.agent.model else None,
819
+ "num_iterations": self.num_iterations,
820
+ }