agno 2.2.13__py3-none-any.whl → 2.4.3__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 (383) hide show
  1. agno/agent/__init__.py +6 -0
  2. agno/agent/agent.py +5252 -3145
  3. agno/agent/remote.py +525 -0
  4. agno/api/api.py +2 -0
  5. agno/client/__init__.py +3 -0
  6. agno/client/a2a/__init__.py +10 -0
  7. agno/client/a2a/client.py +554 -0
  8. agno/client/a2a/schemas.py +112 -0
  9. agno/client/a2a/utils.py +369 -0
  10. agno/client/os.py +2669 -0
  11. agno/compression/__init__.py +3 -0
  12. agno/compression/manager.py +247 -0
  13. agno/culture/manager.py +2 -2
  14. agno/db/base.py +927 -6
  15. agno/db/dynamo/dynamo.py +788 -2
  16. agno/db/dynamo/schemas.py +128 -0
  17. agno/db/dynamo/utils.py +26 -3
  18. agno/db/firestore/firestore.py +674 -50
  19. agno/db/firestore/schemas.py +41 -0
  20. agno/db/firestore/utils.py +25 -10
  21. agno/db/gcs_json/gcs_json_db.py +506 -3
  22. agno/db/gcs_json/utils.py +14 -2
  23. agno/db/in_memory/in_memory_db.py +203 -4
  24. agno/db/in_memory/utils.py +14 -2
  25. agno/db/json/json_db.py +498 -2
  26. agno/db/json/utils.py +14 -2
  27. agno/db/migrations/manager.py +199 -0
  28. agno/db/migrations/utils.py +19 -0
  29. agno/db/migrations/v1_to_v2.py +54 -16
  30. agno/db/migrations/versions/__init__.py +0 -0
  31. agno/db/migrations/versions/v2_3_0.py +977 -0
  32. agno/db/mongo/async_mongo.py +1013 -39
  33. agno/db/mongo/mongo.py +684 -4
  34. agno/db/mongo/schemas.py +48 -0
  35. agno/db/mongo/utils.py +17 -0
  36. agno/db/mysql/__init__.py +2 -1
  37. agno/db/mysql/async_mysql.py +2958 -0
  38. agno/db/mysql/mysql.py +722 -53
  39. agno/db/mysql/schemas.py +77 -11
  40. agno/db/mysql/utils.py +151 -8
  41. agno/db/postgres/async_postgres.py +1254 -137
  42. agno/db/postgres/postgres.py +2316 -93
  43. agno/db/postgres/schemas.py +153 -21
  44. agno/db/postgres/utils.py +22 -7
  45. agno/db/redis/redis.py +531 -3
  46. agno/db/redis/schemas.py +36 -0
  47. agno/db/redis/utils.py +31 -15
  48. agno/db/schemas/evals.py +1 -0
  49. agno/db/schemas/memory.py +20 -9
  50. agno/db/singlestore/schemas.py +70 -1
  51. agno/db/singlestore/singlestore.py +737 -74
  52. agno/db/singlestore/utils.py +13 -3
  53. agno/db/sqlite/async_sqlite.py +1069 -89
  54. agno/db/sqlite/schemas.py +133 -1
  55. agno/db/sqlite/sqlite.py +2203 -165
  56. agno/db/sqlite/utils.py +21 -11
  57. agno/db/surrealdb/models.py +25 -0
  58. agno/db/surrealdb/surrealdb.py +603 -1
  59. agno/db/utils.py +60 -0
  60. agno/eval/__init__.py +26 -3
  61. agno/eval/accuracy.py +25 -12
  62. agno/eval/agent_as_judge.py +871 -0
  63. agno/eval/base.py +29 -0
  64. agno/eval/performance.py +10 -4
  65. agno/eval/reliability.py +22 -13
  66. agno/eval/utils.py +2 -1
  67. agno/exceptions.py +42 -0
  68. agno/hooks/__init__.py +3 -0
  69. agno/hooks/decorator.py +164 -0
  70. agno/integrations/discord/client.py +13 -2
  71. agno/knowledge/__init__.py +4 -0
  72. agno/knowledge/chunking/code.py +90 -0
  73. agno/knowledge/chunking/document.py +65 -4
  74. agno/knowledge/chunking/fixed.py +4 -1
  75. agno/knowledge/chunking/markdown.py +102 -11
  76. agno/knowledge/chunking/recursive.py +2 -2
  77. agno/knowledge/chunking/semantic.py +130 -48
  78. agno/knowledge/chunking/strategy.py +18 -0
  79. agno/knowledge/embedder/azure_openai.py +0 -1
  80. agno/knowledge/embedder/google.py +1 -1
  81. agno/knowledge/embedder/mistral.py +1 -1
  82. agno/knowledge/embedder/nebius.py +1 -1
  83. agno/knowledge/embedder/openai.py +16 -12
  84. agno/knowledge/filesystem.py +412 -0
  85. agno/knowledge/knowledge.py +4261 -1199
  86. agno/knowledge/protocol.py +134 -0
  87. agno/knowledge/reader/arxiv_reader.py +3 -2
  88. agno/knowledge/reader/base.py +9 -7
  89. agno/knowledge/reader/csv_reader.py +91 -42
  90. agno/knowledge/reader/docx_reader.py +9 -10
  91. agno/knowledge/reader/excel_reader.py +225 -0
  92. agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
  93. agno/knowledge/reader/firecrawl_reader.py +3 -2
  94. agno/knowledge/reader/json_reader.py +16 -22
  95. agno/knowledge/reader/markdown_reader.py +15 -14
  96. agno/knowledge/reader/pdf_reader.py +33 -28
  97. agno/knowledge/reader/pptx_reader.py +9 -10
  98. agno/knowledge/reader/reader_factory.py +135 -1
  99. agno/knowledge/reader/s3_reader.py +8 -16
  100. agno/knowledge/reader/tavily_reader.py +3 -3
  101. agno/knowledge/reader/text_reader.py +15 -14
  102. agno/knowledge/reader/utils/__init__.py +17 -0
  103. agno/knowledge/reader/utils/spreadsheet.py +114 -0
  104. agno/knowledge/reader/web_search_reader.py +8 -65
  105. agno/knowledge/reader/website_reader.py +16 -13
  106. agno/knowledge/reader/wikipedia_reader.py +36 -3
  107. agno/knowledge/reader/youtube_reader.py +3 -2
  108. agno/knowledge/remote_content/__init__.py +33 -0
  109. agno/knowledge/remote_content/config.py +266 -0
  110. agno/knowledge/remote_content/remote_content.py +105 -17
  111. agno/knowledge/utils.py +76 -22
  112. agno/learn/__init__.py +71 -0
  113. agno/learn/config.py +463 -0
  114. agno/learn/curate.py +185 -0
  115. agno/learn/machine.py +725 -0
  116. agno/learn/schemas.py +1114 -0
  117. agno/learn/stores/__init__.py +38 -0
  118. agno/learn/stores/decision_log.py +1156 -0
  119. agno/learn/stores/entity_memory.py +3275 -0
  120. agno/learn/stores/learned_knowledge.py +1583 -0
  121. agno/learn/stores/protocol.py +117 -0
  122. agno/learn/stores/session_context.py +1217 -0
  123. agno/learn/stores/user_memory.py +1495 -0
  124. agno/learn/stores/user_profile.py +1220 -0
  125. agno/learn/utils.py +209 -0
  126. agno/media.py +22 -6
  127. agno/memory/__init__.py +14 -1
  128. agno/memory/manager.py +223 -8
  129. agno/memory/strategies/__init__.py +15 -0
  130. agno/memory/strategies/base.py +66 -0
  131. agno/memory/strategies/summarize.py +196 -0
  132. agno/memory/strategies/types.py +37 -0
  133. agno/models/aimlapi/aimlapi.py +17 -0
  134. agno/models/anthropic/claude.py +434 -59
  135. agno/models/aws/bedrock.py +121 -20
  136. agno/models/aws/claude.py +131 -274
  137. agno/models/azure/ai_foundry.py +10 -6
  138. agno/models/azure/openai_chat.py +33 -10
  139. agno/models/base.py +1162 -561
  140. agno/models/cerebras/cerebras.py +120 -24
  141. agno/models/cerebras/cerebras_openai.py +21 -2
  142. agno/models/cohere/chat.py +65 -6
  143. agno/models/cometapi/cometapi.py +18 -1
  144. agno/models/dashscope/dashscope.py +2 -3
  145. agno/models/deepinfra/deepinfra.py +18 -1
  146. agno/models/deepseek/deepseek.py +69 -3
  147. agno/models/fireworks/fireworks.py +18 -1
  148. agno/models/google/gemini.py +959 -89
  149. agno/models/google/utils.py +22 -0
  150. agno/models/groq/groq.py +48 -18
  151. agno/models/huggingface/huggingface.py +17 -6
  152. agno/models/ibm/watsonx.py +16 -6
  153. agno/models/internlm/internlm.py +18 -1
  154. agno/models/langdb/langdb.py +13 -1
  155. agno/models/litellm/chat.py +88 -9
  156. agno/models/litellm/litellm_openai.py +18 -1
  157. agno/models/message.py +24 -5
  158. agno/models/meta/llama.py +40 -13
  159. agno/models/meta/llama_openai.py +22 -21
  160. agno/models/metrics.py +12 -0
  161. agno/models/mistral/mistral.py +8 -4
  162. agno/models/n1n/__init__.py +3 -0
  163. agno/models/n1n/n1n.py +57 -0
  164. agno/models/nebius/nebius.py +6 -7
  165. agno/models/nvidia/nvidia.py +20 -3
  166. agno/models/ollama/__init__.py +2 -0
  167. agno/models/ollama/chat.py +17 -6
  168. agno/models/ollama/responses.py +100 -0
  169. agno/models/openai/__init__.py +2 -0
  170. agno/models/openai/chat.py +117 -26
  171. agno/models/openai/open_responses.py +46 -0
  172. agno/models/openai/responses.py +110 -32
  173. agno/models/openrouter/__init__.py +2 -0
  174. agno/models/openrouter/openrouter.py +67 -2
  175. agno/models/openrouter/responses.py +146 -0
  176. agno/models/perplexity/perplexity.py +19 -1
  177. agno/models/portkey/portkey.py +7 -6
  178. agno/models/requesty/requesty.py +19 -2
  179. agno/models/response.py +20 -2
  180. agno/models/sambanova/sambanova.py +20 -3
  181. agno/models/siliconflow/siliconflow.py +19 -2
  182. agno/models/together/together.py +20 -3
  183. agno/models/vercel/v0.py +20 -3
  184. agno/models/vertexai/claude.py +124 -4
  185. agno/models/vllm/vllm.py +19 -14
  186. agno/models/xai/xai.py +19 -2
  187. agno/os/app.py +467 -137
  188. agno/os/auth.py +253 -5
  189. agno/os/config.py +22 -0
  190. agno/os/interfaces/a2a/a2a.py +7 -6
  191. agno/os/interfaces/a2a/router.py +635 -26
  192. agno/os/interfaces/a2a/utils.py +32 -33
  193. agno/os/interfaces/agui/agui.py +5 -3
  194. agno/os/interfaces/agui/router.py +26 -16
  195. agno/os/interfaces/agui/utils.py +97 -57
  196. agno/os/interfaces/base.py +7 -7
  197. agno/os/interfaces/slack/router.py +16 -7
  198. agno/os/interfaces/slack/slack.py +7 -7
  199. agno/os/interfaces/whatsapp/router.py +35 -7
  200. agno/os/interfaces/whatsapp/security.py +3 -1
  201. agno/os/interfaces/whatsapp/whatsapp.py +11 -8
  202. agno/os/managers.py +326 -0
  203. agno/os/mcp.py +652 -79
  204. agno/os/middleware/__init__.py +4 -0
  205. agno/os/middleware/jwt.py +718 -115
  206. agno/os/middleware/trailing_slash.py +27 -0
  207. agno/os/router.py +105 -1558
  208. agno/os/routers/agents/__init__.py +3 -0
  209. agno/os/routers/agents/router.py +655 -0
  210. agno/os/routers/agents/schema.py +288 -0
  211. agno/os/routers/components/__init__.py +3 -0
  212. agno/os/routers/components/components.py +475 -0
  213. agno/os/routers/database.py +155 -0
  214. agno/os/routers/evals/evals.py +111 -18
  215. agno/os/routers/evals/schemas.py +38 -5
  216. agno/os/routers/evals/utils.py +80 -11
  217. agno/os/routers/health.py +3 -3
  218. agno/os/routers/knowledge/knowledge.py +284 -35
  219. agno/os/routers/knowledge/schemas.py +14 -2
  220. agno/os/routers/memory/memory.py +274 -11
  221. agno/os/routers/memory/schemas.py +44 -3
  222. agno/os/routers/metrics/metrics.py +30 -15
  223. agno/os/routers/metrics/schemas.py +10 -6
  224. agno/os/routers/registry/__init__.py +3 -0
  225. agno/os/routers/registry/registry.py +337 -0
  226. agno/os/routers/session/session.py +143 -14
  227. agno/os/routers/teams/__init__.py +3 -0
  228. agno/os/routers/teams/router.py +550 -0
  229. agno/os/routers/teams/schema.py +280 -0
  230. agno/os/routers/traces/__init__.py +3 -0
  231. agno/os/routers/traces/schemas.py +414 -0
  232. agno/os/routers/traces/traces.py +549 -0
  233. agno/os/routers/workflows/__init__.py +3 -0
  234. agno/os/routers/workflows/router.py +757 -0
  235. agno/os/routers/workflows/schema.py +139 -0
  236. agno/os/schema.py +157 -584
  237. agno/os/scopes.py +469 -0
  238. agno/os/settings.py +3 -0
  239. agno/os/utils.py +574 -185
  240. agno/reasoning/anthropic.py +85 -1
  241. agno/reasoning/azure_ai_foundry.py +93 -1
  242. agno/reasoning/deepseek.py +102 -2
  243. agno/reasoning/default.py +6 -7
  244. agno/reasoning/gemini.py +87 -3
  245. agno/reasoning/groq.py +109 -2
  246. agno/reasoning/helpers.py +6 -7
  247. agno/reasoning/manager.py +1238 -0
  248. agno/reasoning/ollama.py +93 -1
  249. agno/reasoning/openai.py +115 -1
  250. agno/reasoning/vertexai.py +85 -1
  251. agno/registry/__init__.py +3 -0
  252. agno/registry/registry.py +68 -0
  253. agno/remote/__init__.py +3 -0
  254. agno/remote/base.py +581 -0
  255. agno/run/__init__.py +2 -4
  256. agno/run/agent.py +134 -19
  257. agno/run/base.py +49 -1
  258. agno/run/cancel.py +65 -52
  259. agno/run/cancellation_management/__init__.py +9 -0
  260. agno/run/cancellation_management/base.py +78 -0
  261. agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
  262. agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
  263. agno/run/requirement.py +181 -0
  264. agno/run/team.py +111 -19
  265. agno/run/workflow.py +2 -1
  266. agno/session/agent.py +57 -92
  267. agno/session/summary.py +1 -1
  268. agno/session/team.py +62 -115
  269. agno/session/workflow.py +353 -57
  270. agno/skills/__init__.py +17 -0
  271. agno/skills/agent_skills.py +377 -0
  272. agno/skills/errors.py +32 -0
  273. agno/skills/loaders/__init__.py +4 -0
  274. agno/skills/loaders/base.py +27 -0
  275. agno/skills/loaders/local.py +216 -0
  276. agno/skills/skill.py +65 -0
  277. agno/skills/utils.py +107 -0
  278. agno/skills/validator.py +277 -0
  279. agno/table.py +10 -0
  280. agno/team/__init__.py +5 -1
  281. agno/team/remote.py +447 -0
  282. agno/team/team.py +3769 -2202
  283. agno/tools/brandfetch.py +27 -18
  284. agno/tools/browserbase.py +225 -16
  285. agno/tools/crawl4ai.py +3 -0
  286. agno/tools/duckduckgo.py +25 -71
  287. agno/tools/exa.py +0 -21
  288. agno/tools/file.py +14 -13
  289. agno/tools/file_generation.py +12 -6
  290. agno/tools/firecrawl.py +15 -7
  291. agno/tools/function.py +94 -113
  292. agno/tools/google_bigquery.py +11 -2
  293. agno/tools/google_drive.py +4 -3
  294. agno/tools/knowledge.py +9 -4
  295. agno/tools/mcp/mcp.py +301 -18
  296. agno/tools/mcp/multi_mcp.py +269 -14
  297. agno/tools/mem0.py +11 -10
  298. agno/tools/memory.py +47 -46
  299. agno/tools/mlx_transcribe.py +10 -7
  300. agno/tools/models/nebius.py +5 -5
  301. agno/tools/models_labs.py +20 -10
  302. agno/tools/nano_banana.py +151 -0
  303. agno/tools/parallel.py +0 -7
  304. agno/tools/postgres.py +76 -36
  305. agno/tools/python.py +14 -6
  306. agno/tools/reasoning.py +30 -23
  307. agno/tools/redshift.py +406 -0
  308. agno/tools/shopify.py +1519 -0
  309. agno/tools/spotify.py +919 -0
  310. agno/tools/tavily.py +4 -1
  311. agno/tools/toolkit.py +253 -18
  312. agno/tools/websearch.py +93 -0
  313. agno/tools/website.py +1 -1
  314. agno/tools/wikipedia.py +1 -1
  315. agno/tools/workflow.py +56 -48
  316. agno/tools/yfinance.py +12 -11
  317. agno/tracing/__init__.py +12 -0
  318. agno/tracing/exporter.py +161 -0
  319. agno/tracing/schemas.py +276 -0
  320. agno/tracing/setup.py +112 -0
  321. agno/utils/agent.py +251 -10
  322. agno/utils/cryptography.py +22 -0
  323. agno/utils/dttm.py +33 -0
  324. agno/utils/events.py +264 -7
  325. agno/utils/hooks.py +111 -3
  326. agno/utils/http.py +161 -2
  327. agno/utils/mcp.py +49 -8
  328. agno/utils/media.py +22 -1
  329. agno/utils/models/ai_foundry.py +9 -2
  330. agno/utils/models/claude.py +20 -5
  331. agno/utils/models/cohere.py +9 -2
  332. agno/utils/models/llama.py +9 -2
  333. agno/utils/models/mistral.py +4 -2
  334. agno/utils/os.py +0 -0
  335. agno/utils/print_response/agent.py +99 -16
  336. agno/utils/print_response/team.py +223 -24
  337. agno/utils/print_response/workflow.py +0 -2
  338. agno/utils/prompts.py +8 -6
  339. agno/utils/remote.py +23 -0
  340. agno/utils/response.py +1 -13
  341. agno/utils/string.py +91 -2
  342. agno/utils/team.py +62 -12
  343. agno/utils/tokens.py +657 -0
  344. agno/vectordb/base.py +15 -2
  345. agno/vectordb/cassandra/cassandra.py +1 -1
  346. agno/vectordb/chroma/__init__.py +2 -1
  347. agno/vectordb/chroma/chromadb.py +468 -23
  348. agno/vectordb/clickhouse/clickhousedb.py +1 -1
  349. agno/vectordb/couchbase/couchbase.py +6 -2
  350. agno/vectordb/lancedb/lance_db.py +7 -38
  351. agno/vectordb/lightrag/lightrag.py +7 -6
  352. agno/vectordb/milvus/milvus.py +118 -84
  353. agno/vectordb/mongodb/__init__.py +2 -1
  354. agno/vectordb/mongodb/mongodb.py +14 -31
  355. agno/vectordb/pgvector/pgvector.py +120 -66
  356. agno/vectordb/pineconedb/pineconedb.py +2 -19
  357. agno/vectordb/qdrant/__init__.py +2 -1
  358. agno/vectordb/qdrant/qdrant.py +33 -56
  359. agno/vectordb/redis/__init__.py +2 -1
  360. agno/vectordb/redis/redisdb.py +19 -31
  361. agno/vectordb/singlestore/singlestore.py +17 -9
  362. agno/vectordb/surrealdb/surrealdb.py +2 -38
  363. agno/vectordb/weaviate/__init__.py +2 -1
  364. agno/vectordb/weaviate/weaviate.py +7 -3
  365. agno/workflow/__init__.py +5 -1
  366. agno/workflow/agent.py +2 -2
  367. agno/workflow/condition.py +12 -10
  368. agno/workflow/loop.py +28 -9
  369. agno/workflow/parallel.py +21 -13
  370. agno/workflow/remote.py +362 -0
  371. agno/workflow/router.py +12 -9
  372. agno/workflow/step.py +261 -36
  373. agno/workflow/steps.py +12 -8
  374. agno/workflow/types.py +40 -77
  375. agno/workflow/workflow.py +939 -213
  376. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
  377. agno-2.4.3.dist-info/RECORD +677 -0
  378. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
  379. agno/tools/googlesearch.py +0 -98
  380. agno/tools/memori.py +0 -339
  381. agno-2.2.13.dist-info/RECORD +0 -575
  382. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
  383. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/db/utils.py CHANGED
@@ -2,10 +2,36 @@
2
2
 
3
3
  import json
4
4
  from datetime import date, datetime
5
+ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
5
6
  from uuid import UUID
6
7
 
7
8
  from agno.models.message import Message
8
9
  from agno.models.metrics import Metrics
10
+ from agno.utils.log import log_error, log_warning
11
+
12
+ if TYPE_CHECKING:
13
+ from agno.db.base import BaseDb
14
+
15
+
16
+ def get_sort_value(record: Dict[str, Any], sort_by: str) -> Any:
17
+ """Get the sort value for a record, with fallback to created_at for updated_at.
18
+
19
+ When sorting by 'updated_at', this function falls back to 'created_at' if
20
+ 'updated_at' is None. This ensures pre-2.0 records (which may have NULL
21
+ updated_at values) are sorted correctly by their creation time.
22
+
23
+ Args:
24
+ record: The record dictionary to get the sort value from
25
+ sort_by: The field to sort by
26
+
27
+ Returns:
28
+ The value to use for sorting
29
+ """
30
+ value = record.get(sort_by)
31
+ # For updated_at, fall back to created_at if updated_at is None
32
+ if value is None and sort_by == "updated_at":
33
+ value = record.get("created_at")
34
+ return value
9
35
 
10
36
 
11
37
  class CustomJSONEncoder(json.JSONEncoder):
@@ -20,6 +46,8 @@ class CustomJSONEncoder(json.JSONEncoder):
20
46
  return obj.to_dict()
21
47
  elif isinstance(obj, Metrics):
22
48
  return obj.to_dict()
49
+ elif isinstance(obj, type):
50
+ return str(obj)
23
51
 
24
52
  return super().default(obj)
25
53
 
@@ -114,3 +142,35 @@ def deserialize_session_json_fields(session: dict) -> dict:
114
142
  log_warning(f"Warning: Could not parse runs as JSON, keeping as string: {e}")
115
143
 
116
144
  return session
145
+
146
+
147
+ def db_from_dict(db_data: Dict[str, Any]) -> Optional[Union["BaseDb"]]:
148
+ """
149
+ Create a database instance from a dictionary.
150
+
151
+ Args:
152
+ db_data: Dictionary containing database configuration
153
+
154
+ Returns:
155
+ Database instance or None if creation fails
156
+ """
157
+ db_type = db_data.get("type")
158
+ if db_type == "postgres":
159
+ try:
160
+ from agno.db.postgres import PostgresDb
161
+
162
+ return PostgresDb.from_dict(db_data)
163
+ except Exception as e:
164
+ log_error(f"Error reconstructing PostgresDb from dictionary: {e}")
165
+ return None
166
+ elif db_type == "sqlite":
167
+ try:
168
+ from agno.db.sqlite import SqliteDb
169
+
170
+ return SqliteDb.from_dict(db_data)
171
+ except Exception as e:
172
+ log_error(f"Error reconstructing SqliteDb from dictionary: {e}")
173
+ return None
174
+ else:
175
+ log_warning(f"Unknown database type: {db_type}")
176
+ return None
agno/eval/__init__.py CHANGED
@@ -1,14 +1,37 @@
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
1
+ from agno.eval.base import BaseEval
4
2
 
5
3
  __all__ = [
6
4
  "AccuracyAgentResponse",
7
5
  "AccuracyEvaluation",
8
6
  "AccuracyResult",
9
7
  "AccuracyEval",
8
+ "AgentAsJudgeEval",
9
+ "AgentAsJudgeEvaluation",
10
+ "AgentAsJudgeResult",
11
+ "BaseEval",
10
12
  "PerformanceEval",
11
13
  "PerformanceResult",
12
14
  "ReliabilityEval",
13
15
  "ReliabilityResult",
14
16
  ]
17
+
18
+
19
+ def __getattr__(name: str):
20
+ """Lazy import for eval implementations to avoid circular imports with Agent."""
21
+ if name in ("AccuracyAgentResponse", "AccuracyEval", "AccuracyEvaluation", "AccuracyResult"):
22
+ from agno.eval import accuracy
23
+
24
+ return getattr(accuracy, name)
25
+ elif name in ("AgentAsJudgeEval", "AgentAsJudgeEvaluation", "AgentAsJudgeResult"):
26
+ from agno.eval import agent_as_judge
27
+
28
+ return getattr(agent_as_judge, name)
29
+ elif name in ("PerformanceEval", "PerformanceResult"):
30
+ from agno.eval import performance
31
+
32
+ return getattr(performance, name)
33
+ elif name in ("ReliabilityEval", "ReliabilityResult"):
34
+ from agno.eval import reliability
35
+
36
+ return getattr(reliability, name)
37
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
agno/eval/accuracy.py CHANGED
@@ -282,7 +282,8 @@ Remember: You must only compare the agent_output to the expected_output. The exp
282
282
  ) -> Optional[AccuracyEvaluation]:
283
283
  """Orchestrate the evaluation process."""
284
284
  try:
285
- accuracy_agent_response = evaluator_agent.run(evaluation_input).content
285
+ response = evaluator_agent.run(evaluation_input, stream=False)
286
+ accuracy_agent_response = response.content
286
287
  if accuracy_agent_response is None or not isinstance(accuracy_agent_response, AccuracyAgentResponse):
287
288
  raise EvalError(f"Evaluator Agent returned an invalid response: {accuracy_agent_response}")
288
289
  return AccuracyEvaluation(
@@ -306,7 +307,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
306
307
  ) -> Optional[AccuracyEvaluation]:
307
308
  """Orchestrate the evaluation process asynchronously."""
308
309
  try:
309
- response = await evaluator_agent.arun(evaluation_input)
310
+ response = await evaluator_agent.arun(evaluation_input, stream=False)
310
311
  accuracy_agent_response = response.content
311
312
  if accuracy_agent_response is None or not isinstance(accuracy_agent_response, AccuracyAgentResponse):
312
313
  raise EvalError(f"Evaluator Agent returned an invalid response: {accuracy_agent_response}")
@@ -359,10 +360,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
359
360
  status = Status(f"Running evaluation {i + 1}...", spinner="dots", speed=1.0, refresh_per_second=10)
360
361
  live_log.update(status)
361
362
 
363
+ agent_session_id = f"eval_{self.eval_id}_{i + 1}"
364
+
362
365
  if self.agent is not None:
363
- output = self.agent.run(input=eval_input).content
366
+ agent_response = self.agent.run(input=eval_input, session_id=agent_session_id, stream=False)
367
+ output = agent_response.content
364
368
  elif self.team is not None:
365
- output = self.team.run(input=eval_input).content
369
+ team_response = self.team.run(input=eval_input, session_id=agent_session_id, stream=False)
370
+ output = team_response.content
366
371
 
367
372
  if not output:
368
373
  logger.error(f"Failed to generate a valid answer on iteration {i + 1}: {output}")
@@ -500,12 +505,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
500
505
  status = Status(f"Running evaluation {i + 1}...", spinner="dots", speed=1.0, refresh_per_second=10)
501
506
  live_log.update(status)
502
507
 
508
+ agent_session_id = f"eval_{self.eval_id}_{i + 1}"
509
+
503
510
  if self.agent is not None:
504
- response = await self.agent.arun(input=eval_input)
505
- output = response.content
511
+ agent_response = await self.agent.arun(input=eval_input, session_id=agent_session_id, stream=False)
512
+ output = agent_response.content
506
513
  elif self.team is not None:
507
- response = await self.team.arun(input=eval_input) # type: ignore
508
- output = response.content
514
+ team_response = await self.team.arun(input=eval_input, session_id=agent_session_id, stream=False)
515
+ output = team_response.content
509
516
 
510
517
  if not output:
511
518
  logger.error(f"Failed to generate a valid answer on iteration {i + 1}: {output}")
@@ -612,11 +619,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
612
619
  print_results: bool = True,
613
620
  ) -> Optional[AccuracyResult]:
614
621
  """Run the evaluation logic against the given answer, instead of generating an answer with the Agent"""
622
+ # Generate unique run_id for this execution (don't modify self.eval_id due to concurrency)
623
+ run_id = str(uuid4())
624
+
615
625
  set_log_level_to_debug() if self.debug_mode else set_log_level_to_info()
616
626
 
617
627
  self.result = AccuracyResult()
618
628
 
619
- logger.debug(f"************ Evaluation Start: {self.eval_id} ************")
629
+ logger.debug(f"************ Evaluation Start: {run_id} ************")
620
630
 
621
631
  evaluator_agent = self.get_evaluator_agent()
622
632
  eval_input = self.get_eval_input()
@@ -721,7 +731,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
721
731
  ),
722
732
  )
723
733
 
724
- logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
734
+ logger.debug(f"*********** Evaluation End: {run_id} ***********")
725
735
  return self.result
726
736
 
727
737
  async def arun_with_output(
@@ -732,11 +742,14 @@ Remember: You must only compare the agent_output to the expected_output. The exp
732
742
  print_results: bool = True,
733
743
  ) -> Optional[AccuracyResult]:
734
744
  """Run the evaluation logic against the given answer, instead of generating an answer with the Agent"""
745
+ # Generate unique run_id for this execution (don't modify self.eval_id due to concurrency)
746
+ run_id = str(uuid4())
747
+
735
748
  set_log_level_to_debug() if self.debug_mode else set_log_level_to_info()
736
749
 
737
750
  self.result = AccuracyResult()
738
751
 
739
- logger.debug(f"************ Evaluation Start: {self.eval_id} ************")
752
+ logger.debug(f"************ Evaluation Start: {run_id} ************")
740
753
 
741
754
  evaluator_agent = self.get_evaluator_agent()
742
755
  eval_input = self.get_eval_input()
@@ -820,7 +833,7 @@ Remember: You must only compare the agent_output to the expected_output. The exp
820
833
  eval_input=log_eval_input,
821
834
  )
822
835
 
823
- logger.debug(f"*********** Evaluation End: {self.eval_id} ***********")
836
+ logger.debug(f"*********** Evaluation End: {run_id} ***********")
824
837
  return self.result
825
838
 
826
839
  def _get_telemetry_data(self) -> Dict[str, Any]: