agno 0.1.2__py3-none-any.whl → 2.3.13__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 (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  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/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1791 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1312 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,450 @@
1
+ import logging
2
+ from copy import deepcopy
3
+ from typing import List, Optional, Union, cast
4
+
5
+ from fastapi import APIRouter, Depends, HTTPException, Query
6
+
7
+ from agno.agent.agent import Agent
8
+ from agno.db.base import AsyncBaseDb, BaseDb
9
+ from agno.db.schemas.evals import EvalFilterType, EvalType
10
+ from agno.models.utils import get_model
11
+ from agno.os.auth import get_authentication_dependency
12
+ from agno.os.routers.evals.schemas import (
13
+ DeleteEvalRunsRequest,
14
+ EvalRunInput,
15
+ EvalSchema,
16
+ UpdateEvalRunRequest,
17
+ )
18
+ from agno.os.routers.evals.utils import (
19
+ run_accuracy_eval,
20
+ run_agent_as_judge_eval,
21
+ run_performance_eval,
22
+ run_reliability_eval,
23
+ )
24
+ from agno.os.schema import (
25
+ BadRequestResponse,
26
+ InternalServerErrorResponse,
27
+ NotFoundResponse,
28
+ PaginatedResponse,
29
+ PaginationInfo,
30
+ SortOrder,
31
+ UnauthenticatedResponse,
32
+ ValidationErrorResponse,
33
+ )
34
+ from agno.os.settings import AgnoAPISettings
35
+ from agno.os.utils import get_agent_by_id, get_db, get_team_by_id
36
+ from agno.team.team import Team
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
+ def get_eval_router(
42
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
43
+ agents: Optional[List[Agent]] = None,
44
+ teams: Optional[List[Team]] = None,
45
+ settings: AgnoAPISettings = AgnoAPISettings(),
46
+ ) -> APIRouter:
47
+ """Create eval router with comprehensive OpenAPI documentation for agent/team evaluation endpoints."""
48
+ router = APIRouter(
49
+ dependencies=[Depends(get_authentication_dependency(settings))],
50
+ tags=["Evals"],
51
+ responses={
52
+ 400: {"description": "Bad Request", "model": BadRequestResponse},
53
+ 401: {"description": "Unauthorized", "model": UnauthenticatedResponse},
54
+ 404: {"description": "Not Found", "model": NotFoundResponse},
55
+ 422: {"description": "Validation Error", "model": ValidationErrorResponse},
56
+ 500: {"description": "Internal Server Error", "model": InternalServerErrorResponse},
57
+ },
58
+ )
59
+ return attach_routes(router=router, dbs=dbs, agents=agents, teams=teams)
60
+
61
+
62
+ def attach_routes(
63
+ router: APIRouter,
64
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
65
+ agents: Optional[List[Agent]] = None,
66
+ teams: Optional[List[Team]] = None,
67
+ ) -> APIRouter:
68
+ @router.get(
69
+ "/eval-runs",
70
+ response_model=PaginatedResponse[EvalSchema],
71
+ status_code=200,
72
+ operation_id="get_eval_runs",
73
+ summary="List Evaluation Runs",
74
+ description=(
75
+ "Retrieve paginated evaluation runs with filtering and sorting options. "
76
+ "Filter by agent, team, workflow, model, or evaluation type."
77
+ ),
78
+ responses={
79
+ 200: {
80
+ "description": "Evaluation runs retrieved successfully",
81
+ "content": {
82
+ "application/json": {
83
+ "example": {
84
+ "data": [
85
+ {
86
+ "id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
87
+ "agent_id": "basic-agent",
88
+ "model_id": "gpt-4o",
89
+ "model_provider": "OpenAI",
90
+ "team_id": None,
91
+ "workflow_id": None,
92
+ "name": "Test ",
93
+ "evaluated_component_name": None,
94
+ "eval_type": "reliability",
95
+ "eval_data": {
96
+ "eval_status": "PASSED",
97
+ "failed_tool_calls": [],
98
+ "passed_tool_calls": ["multiply"],
99
+ },
100
+ "eval_input": {"expected_tool_calls": ["multiply"]},
101
+ "created_at": "2025-08-27T15:41:59Z",
102
+ "updated_at": "2025-08-27T15:41:59Z",
103
+ }
104
+ ]
105
+ }
106
+ }
107
+ },
108
+ }
109
+ },
110
+ )
111
+ async def get_eval_runs(
112
+ agent_id: Optional[str] = Query(default=None, description="Agent ID"),
113
+ team_id: Optional[str] = Query(default=None, description="Team ID"),
114
+ workflow_id: Optional[str] = Query(default=None, description="Workflow ID"),
115
+ model_id: Optional[str] = Query(default=None, description="Model ID"),
116
+ filter_type: Optional[EvalFilterType] = Query(default=None, description="Filter type", alias="type"),
117
+ eval_types: Optional[List[EvalType]] = Depends(parse_eval_types_filter),
118
+ limit: Optional[int] = Query(default=20, description="Number of eval runs to return"),
119
+ page: Optional[int] = Query(default=1, description="Page number"),
120
+ sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
121
+ sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
122
+ db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
123
+ table: Optional[str] = Query(default=None, description="The database table to use"),
124
+ ) -> PaginatedResponse[EvalSchema]:
125
+ db = await get_db(dbs, db_id, table)
126
+
127
+ # TODO: Delete me:
128
+ # Filtering out agent-as-judge by default for now,
129
+ # as they are not supported yet in the AgentOS UI.
130
+ eval_types = eval_types or [
131
+ EvalType.ACCURACY,
132
+ EvalType.PERFORMANCE,
133
+ EvalType.RELIABILITY,
134
+ ]
135
+
136
+ if isinstance(db, AsyncBaseDb):
137
+ db = cast(AsyncBaseDb, db)
138
+ eval_runs, total_count = await db.get_eval_runs(
139
+ limit=limit,
140
+ page=page,
141
+ sort_by=sort_by,
142
+ sort_order=sort_order,
143
+ agent_id=agent_id,
144
+ team_id=team_id,
145
+ workflow_id=workflow_id,
146
+ model_id=model_id,
147
+ eval_type=eval_types,
148
+ filter_type=filter_type,
149
+ deserialize=False,
150
+ )
151
+ else:
152
+ eval_runs, total_count = db.get_eval_runs( # type: ignore
153
+ limit=limit,
154
+ page=page,
155
+ sort_by=sort_by,
156
+ sort_order=sort_order,
157
+ agent_id=agent_id,
158
+ team_id=team_id,
159
+ workflow_id=workflow_id,
160
+ model_id=model_id,
161
+ eval_type=eval_types,
162
+ filter_type=filter_type,
163
+ deserialize=False,
164
+ )
165
+
166
+ return PaginatedResponse(
167
+ data=[EvalSchema.from_dict(eval_run) for eval_run in eval_runs], # type: ignore
168
+ meta=PaginationInfo(
169
+ page=page,
170
+ limit=limit,
171
+ total_count=total_count, # type: ignore
172
+ total_pages=(total_count + limit - 1) // limit if limit is not None and limit > 0 else 0, # type: ignore
173
+ ),
174
+ )
175
+
176
+ @router.get(
177
+ "/eval-runs/{eval_run_id}",
178
+ response_model=EvalSchema,
179
+ status_code=200,
180
+ operation_id="get_eval_run",
181
+ summary="Get Evaluation Run",
182
+ description="Retrieve detailed results and metrics for a specific evaluation run.",
183
+ responses={
184
+ 200: {
185
+ "description": "Evaluation run details retrieved successfully",
186
+ "content": {
187
+ "application/json": {
188
+ "example": {
189
+ "id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
190
+ "agent_id": "basic-agent",
191
+ "model_id": "gpt-4o",
192
+ "model_provider": "OpenAI",
193
+ "team_id": None,
194
+ "workflow_id": None,
195
+ "name": "Test ",
196
+ "evaluated_component_name": None,
197
+ "eval_type": "reliability",
198
+ "eval_data": {
199
+ "eval_status": "PASSED",
200
+ "failed_tool_calls": [],
201
+ "passed_tool_calls": ["multiply"],
202
+ },
203
+ "eval_input": {"expected_tool_calls": ["multiply"]},
204
+ "created_at": "2025-08-27T15:41:59Z",
205
+ "updated_at": "2025-08-27T15:41:59Z",
206
+ }
207
+ }
208
+ },
209
+ },
210
+ 404: {"description": "Evaluation run not found", "model": NotFoundResponse},
211
+ },
212
+ )
213
+ async def get_eval_run(
214
+ eval_run_id: str,
215
+ db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
216
+ table: Optional[str] = Query(default=None, description="Table to query eval run from"),
217
+ ) -> EvalSchema:
218
+ db = await get_db(dbs, db_id, table)
219
+ if isinstance(db, AsyncBaseDb):
220
+ db = cast(AsyncBaseDb, db)
221
+ eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
222
+ else:
223
+ eval_run = db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
224
+ if not eval_run:
225
+ raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
226
+
227
+ return EvalSchema.from_dict(eval_run) # type: ignore
228
+
229
+ @router.delete(
230
+ "/eval-runs",
231
+ status_code=204,
232
+ operation_id="delete_eval_runs",
233
+ summary="Delete Evaluation Runs",
234
+ description="Delete multiple evaluation runs by their IDs. This action cannot be undone.",
235
+ responses={
236
+ 204: {},
237
+ 500: {"description": "Failed to delete evaluation runs", "model": InternalServerErrorResponse},
238
+ },
239
+ )
240
+ async def delete_eval_runs(
241
+ request: DeleteEvalRunsRequest,
242
+ db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
243
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
244
+ ) -> None:
245
+ try:
246
+ db = await get_db(dbs, db_id, table)
247
+ if isinstance(db, AsyncBaseDb):
248
+ db = cast(AsyncBaseDb, db)
249
+ await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
250
+ else:
251
+ db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
252
+ except Exception as e:
253
+ raise HTTPException(status_code=500, detail=f"Failed to delete eval runs: {e}")
254
+
255
+ @router.patch(
256
+ "/eval-runs/{eval_run_id}",
257
+ response_model=EvalSchema,
258
+ status_code=200,
259
+ operation_id="update_eval_run",
260
+ summary="Update Evaluation Run",
261
+ description="Update the name or other properties of an existing evaluation run.",
262
+ responses={
263
+ 200: {
264
+ "description": "Evaluation run updated successfully",
265
+ "content": {
266
+ "application/json": {
267
+ "example": {
268
+ "id": "a03fa2f4-900d-482d-afe0-470d4cd8d1f4",
269
+ "agent_id": "basic-agent",
270
+ "model_id": "gpt-4o",
271
+ "model_provider": "OpenAI",
272
+ "team_id": None,
273
+ "workflow_id": None,
274
+ "name": "Test ",
275
+ "evaluated_component_name": None,
276
+ "eval_type": "reliability",
277
+ "eval_data": {
278
+ "eval_status": "PASSED",
279
+ "failed_tool_calls": [],
280
+ "passed_tool_calls": ["multiply"],
281
+ },
282
+ "eval_input": {"expected_tool_calls": ["multiply"]},
283
+ "created_at": "2025-08-27T15:41:59Z",
284
+ "updated_at": "2025-08-27T15:41:59Z",
285
+ }
286
+ }
287
+ },
288
+ },
289
+ 404: {"description": "Evaluation run not found", "model": NotFoundResponse},
290
+ 500: {"description": "Failed to update evaluation run", "model": InternalServerErrorResponse},
291
+ },
292
+ )
293
+ async def update_eval_run(
294
+ eval_run_id: str,
295
+ request: UpdateEvalRunRequest,
296
+ db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
297
+ table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
298
+ ) -> EvalSchema:
299
+ try:
300
+ db = await get_db(dbs, db_id, table)
301
+ if isinstance(db, AsyncBaseDb):
302
+ db = cast(AsyncBaseDb, db)
303
+ eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
304
+ else:
305
+ eval_run = db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
306
+ except Exception as e:
307
+ raise HTTPException(status_code=500, detail=f"Failed to rename eval run: {e}")
308
+
309
+ if not eval_run:
310
+ raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
311
+
312
+ return EvalSchema.from_dict(eval_run) # type: ignore
313
+
314
+ @router.post(
315
+ "/eval-runs",
316
+ response_model=EvalSchema,
317
+ status_code=200,
318
+ operation_id="run_eval",
319
+ summary="Execute Evaluation",
320
+ description=(
321
+ "Run evaluation tests on agents or teams. Supports accuracy, agent-as-judge, performance, and reliability evaluations. "
322
+ "Requires either agent_id or team_id, but not both."
323
+ ),
324
+ responses={
325
+ 200: {
326
+ "description": "Evaluation executed successfully",
327
+ "content": {
328
+ "application/json": {
329
+ "example": {
330
+ "id": "f2b2d72f-e9e2-4f0e-8810-0a7e1ff58614",
331
+ "agent_id": "basic-agent",
332
+ "model_id": "gpt-4o",
333
+ "model_provider": "OpenAI",
334
+ "team_id": None,
335
+ "workflow_id": None,
336
+ "name": None,
337
+ "evaluated_component_name": None,
338
+ "eval_type": "reliability",
339
+ "eval_data": {
340
+ "eval_status": "PASSED",
341
+ "failed_tool_calls": [],
342
+ "passed_tool_calls": ["multiply"],
343
+ },
344
+ "created_at": "2025-08-27T15:41:59Z",
345
+ "updated_at": "2025-08-27T15:41:59Z",
346
+ }
347
+ }
348
+ },
349
+ },
350
+ 400: {"description": "Invalid request - provide either agent_id or team_id", "model": BadRequestResponse},
351
+ 404: {"description": "Agent or team not found", "model": NotFoundResponse},
352
+ },
353
+ )
354
+ async def run_eval(
355
+ eval_run_input: EvalRunInput,
356
+ db_id: Optional[str] = Query(default=None, description="Database ID to use for evaluation"),
357
+ table: Optional[str] = Query(default=None, description="Table to use for evaluation"),
358
+ ) -> Optional[EvalSchema]:
359
+ db = await get_db(dbs, db_id, table)
360
+
361
+ if eval_run_input.agent_id and eval_run_input.team_id:
362
+ raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
363
+
364
+ if eval_run_input.agent_id:
365
+ agent = get_agent_by_id(agent_id=eval_run_input.agent_id, agents=agents)
366
+ if not agent:
367
+ raise HTTPException(status_code=404, detail=f"Agent with id '{eval_run_input.agent_id}' not found")
368
+
369
+ default_model = None
370
+ if (
371
+ hasattr(agent, "model")
372
+ and agent.model is not None
373
+ and eval_run_input.model_id is not None
374
+ and eval_run_input.model_provider is not None
375
+ ):
376
+ default_model = deepcopy(agent.model)
377
+ if eval_run_input.model_id != agent.model.id or eval_run_input.model_provider != agent.model.provider:
378
+ model_provider = eval_run_input.model_provider.lower()
379
+ model_id = eval_run_input.model_id.lower()
380
+ model_string = f"{model_provider}:{model_id}"
381
+ model = get_model(model_string)
382
+ agent.model = model
383
+
384
+ team = None
385
+
386
+ elif eval_run_input.team_id:
387
+ team = get_team_by_id(team_id=eval_run_input.team_id, teams=teams)
388
+ if not team:
389
+ raise HTTPException(status_code=404, detail=f"Team with id '{eval_run_input.team_id}' not found")
390
+
391
+ # If model_id/model_provider specified, override team's model temporarily
392
+ default_model = None
393
+ if (
394
+ hasattr(team, "model")
395
+ and team.model is not None
396
+ and eval_run_input.model_id is not None
397
+ and eval_run_input.model_provider is not None
398
+ ):
399
+ default_model = deepcopy(team.model) # Save original
400
+ if eval_run_input.model_id != team.model.id or eval_run_input.model_provider != team.model.provider:
401
+ model_provider = eval_run_input.model_provider.lower()
402
+ model_id = eval_run_input.model_id.lower()
403
+ model_string = f"{model_provider}:{model_id}"
404
+ model = get_model(model_string)
405
+ team.model = model # Override temporarily
406
+
407
+ agent = None
408
+
409
+ else:
410
+ raise HTTPException(status_code=400, detail="One of agent_id or team_id must be provided")
411
+
412
+ # Run the evaluation
413
+ if eval_run_input.eval_type == EvalType.ACCURACY:
414
+ return await run_accuracy_eval(
415
+ eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
416
+ )
417
+
418
+ elif eval_run_input.eval_type == EvalType.AGENT_AS_JUDGE:
419
+ return await run_agent_as_judge_eval(
420
+ eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
421
+ )
422
+
423
+ elif eval_run_input.eval_type == EvalType.PERFORMANCE:
424
+ return await run_performance_eval(
425
+ eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
426
+ )
427
+
428
+ else:
429
+ return await run_reliability_eval(
430
+ eval_run_input=eval_run_input, db=db, agent=agent, team=team, default_model=default_model
431
+ )
432
+
433
+ return router
434
+
435
+
436
+ def parse_eval_types_filter(
437
+ eval_types: Optional[str] = Query(
438
+ default=None,
439
+ description="Comma-separated eval types (accuracy,agent_as_judge,performance,reliability)",
440
+ examples=["accuracy,agent_as_judge,performance,reliability"],
441
+ ),
442
+ ) -> Optional[List[EvalType]]:
443
+ """Parse comma-separated eval types into EvalType enums for filtering evaluation runs."""
444
+ if not eval_types:
445
+ return None
446
+ try:
447
+ return [EvalType(item.strip()) for item in eval_types.split(",")]
448
+ except ValueError as e:
449
+ valid_types = ", ".join([t.value for t in EvalType])
450
+ raise HTTPException(status_code=422, detail=f"Invalid eval_type: {e}. Valid types: {valid_types}")
@@ -0,0 +1,174 @@
1
+ from dataclasses import asdict
2
+ from datetime import datetime, timezone
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from agno.db.schemas.evals import EvalType
8
+ from agno.eval import AccuracyResult, AgentAsJudgeResult, PerformanceResult, ReliabilityResult
9
+ from agno.eval.accuracy import AccuracyEval
10
+ from agno.eval.agent_as_judge import AgentAsJudgeEval
11
+ from agno.eval.performance import PerformanceEval
12
+ from agno.eval.reliability import ReliabilityEval
13
+
14
+
15
+ class EvalRunInput(BaseModel):
16
+ agent_id: Optional[str] = Field(None, description="Agent ID to evaluate")
17
+ team_id: Optional[str] = Field(None, description="Team ID to evaluate")
18
+
19
+ model_id: Optional[str] = Field(None, description="Model ID to use for evaluation")
20
+ model_provider: Optional[str] = Field(None, description="Model provider name")
21
+ eval_type: EvalType = Field(..., description="Type of evaluation to run (accuracy, performance, or reliability)")
22
+ input: str = Field(..., description="Input text/query for the evaluation", min_length=1)
23
+ additional_guidelines: Optional[str] = Field(None, description="Additional guidelines for the evaluation")
24
+ additional_context: Optional[str] = Field(None, description="Additional context for the evaluation")
25
+ num_iterations: int = Field(1, description="Number of times to run the evaluation", ge=1, le=100)
26
+ name: Optional[str] = Field(None, description="Name for this evaluation run")
27
+
28
+ # Accuracy eval specific fields
29
+ expected_output: Optional[str] = Field(None, description="Expected output for accuracy evaluation")
30
+
31
+ # AgentAsJudge eval specific fields
32
+ criteria: Optional[str] = Field(None, description="Evaluation criteria for agent-as-judge evaluation")
33
+ scoring_strategy: Optional[Literal["numeric", "binary"]] = Field(
34
+ "binary", description="Scoring strategy: 'numeric' (1-10 with threshold) or 'binary' (PASS/FAIL)"
35
+ )
36
+ threshold: Optional[int] = Field(
37
+ 7, description="Score threshold for pass/fail (1-10), only used with numeric scoring", ge=1, le=10
38
+ )
39
+
40
+ # Performance eval specific fields
41
+ warmup_runs: int = Field(0, description="Number of warmup runs before measuring performance", ge=0, le=10)
42
+
43
+ # Reliability eval specific fields
44
+ expected_tool_calls: Optional[List[str]] = Field(None, description="Expected tool calls for reliability evaluation")
45
+
46
+
47
+ class EvalSchema(BaseModel):
48
+ id: str = Field(..., description="Unique identifier for the evaluation run")
49
+
50
+ agent_id: Optional[str] = Field(None, description="Agent ID that was evaluated")
51
+ model_id: Optional[str] = Field(None, description="Model ID used in evaluation")
52
+ model_provider: Optional[str] = Field(None, description="Model provider name")
53
+ team_id: Optional[str] = Field(None, description="Team ID that was evaluated")
54
+ workflow_id: Optional[str] = Field(None, description="Workflow ID that was evaluated")
55
+ name: Optional[str] = Field(None, description="Name of the evaluation run")
56
+ evaluated_component_name: Optional[str] = Field(None, description="Name of the evaluated component")
57
+ eval_type: EvalType = Field(..., description="Type of evaluation (accuracy, performance, or reliability)")
58
+ eval_data: Dict[str, Any] = Field(..., description="Evaluation results and metrics")
59
+ eval_input: Optional[Dict[str, Any]] = Field(None, description="Input parameters used for the evaluation")
60
+ created_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was created")
61
+ updated_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was last updated")
62
+
63
+ @classmethod
64
+ def from_dict(cls, eval_run: Dict[str, Any]) -> "EvalSchema":
65
+ return cls(
66
+ id=eval_run["run_id"],
67
+ name=eval_run.get("name"),
68
+ agent_id=eval_run.get("agent_id"),
69
+ model_id=eval_run.get("model_id"),
70
+ model_provider=eval_run.get("model_provider"),
71
+ team_id=eval_run.get("team_id"),
72
+ workflow_id=eval_run.get("workflow_id"),
73
+ evaluated_component_name=eval_run.get("evaluated_component_name"),
74
+ eval_type=eval_run["eval_type"],
75
+ eval_data=eval_run["eval_data"],
76
+ eval_input=eval_run.get("eval_input"),
77
+ created_at=datetime.fromtimestamp(eval_run["created_at"], tz=timezone.utc),
78
+ updated_at=datetime.fromtimestamp(eval_run["updated_at"], tz=timezone.utc),
79
+ )
80
+
81
+ @classmethod
82
+ def from_accuracy_eval(cls, accuracy_eval: AccuracyEval, result: AccuracyResult) -> "EvalSchema":
83
+ model_provider = (
84
+ accuracy_eval.agent.model.provider
85
+ if accuracy_eval.agent and accuracy_eval.agent.model
86
+ else accuracy_eval.team.model.provider
87
+ if accuracy_eval.team and accuracy_eval.team.model
88
+ else None
89
+ )
90
+ return cls(
91
+ id=accuracy_eval.eval_id,
92
+ name=accuracy_eval.name,
93
+ agent_id=accuracy_eval.agent.id if accuracy_eval.agent else None,
94
+ team_id=accuracy_eval.team.id if accuracy_eval.team else None,
95
+ workflow_id=None,
96
+ model_id=accuracy_eval.agent.model.id if accuracy_eval.agent else accuracy_eval.team.model.id, # type: ignore
97
+ model_provider=model_provider,
98
+ eval_type=EvalType.ACCURACY,
99
+ eval_data=asdict(result),
100
+ )
101
+
102
+ @classmethod
103
+ def from_agent_as_judge_eval(
104
+ cls,
105
+ agent_as_judge_eval: AgentAsJudgeEval,
106
+ result: AgentAsJudgeResult,
107
+ model_id: Optional[str] = None,
108
+ model_provider: Optional[str] = None,
109
+ agent_id: Optional[str] = None,
110
+ team_id: Optional[str] = None,
111
+ ) -> "EvalSchema":
112
+ return cls(
113
+ id=result.run_id,
114
+ name=agent_as_judge_eval.name,
115
+ agent_id=agent_id,
116
+ team_id=team_id,
117
+ workflow_id=None,
118
+ model_id=model_id,
119
+ model_provider=model_provider,
120
+ eval_type=EvalType.AGENT_AS_JUDGE,
121
+ eval_data=asdict(result),
122
+ )
123
+
124
+ @classmethod
125
+ def from_performance_eval(
126
+ cls,
127
+ performance_eval: PerformanceEval,
128
+ result: PerformanceResult,
129
+ model_id: Optional[str] = None,
130
+ model_provider: Optional[str] = None,
131
+ agent_id: Optional[str] = None,
132
+ team_id: Optional[str] = None,
133
+ ) -> "EvalSchema":
134
+ return cls(
135
+ id=performance_eval.eval_id,
136
+ name=performance_eval.name,
137
+ agent_id=agent_id,
138
+ team_id=team_id,
139
+ workflow_id=None,
140
+ model_id=model_id,
141
+ model_provider=model_provider,
142
+ eval_type=EvalType.PERFORMANCE,
143
+ eval_data=asdict(result),
144
+ )
145
+
146
+ @classmethod
147
+ def from_reliability_eval(
148
+ cls,
149
+ reliability_eval: ReliabilityEval,
150
+ result: ReliabilityResult,
151
+ model_id: Optional[str] = None,
152
+ model_provider: Optional[str] = None,
153
+ agent_id: Optional[str] = None,
154
+ team_id: Optional[str] = None,
155
+ ) -> "EvalSchema":
156
+ return cls(
157
+ id=reliability_eval.eval_id,
158
+ name=reliability_eval.name,
159
+ agent_id=agent_id,
160
+ team_id=team_id,
161
+ workflow_id=None,
162
+ model_id=model_id,
163
+ model_provider=model_provider,
164
+ eval_type=EvalType.RELIABILITY,
165
+ eval_data=asdict(result),
166
+ )
167
+
168
+
169
+ class DeleteEvalRunsRequest(BaseModel):
170
+ eval_run_ids: List[str] = Field(..., description="List of evaluation run IDs to delete", min_length=1)
171
+
172
+
173
+ class UpdateEvalRunRequest(BaseModel):
174
+ name: str = Field(..., description="New name for the evaluation run", min_length=1, max_length=255)