agno 2.0.1__py3-none-any.whl → 2.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. agno/agent/agent.py +6015 -2823
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/culture/__init__.py +3 -0
  5. agno/culture/manager.py +956 -0
  6. agno/db/async_postgres/__init__.py +3 -0
  7. agno/db/base.py +385 -6
  8. agno/db/dynamo/dynamo.py +388 -81
  9. agno/db/dynamo/schemas.py +47 -10
  10. agno/db/dynamo/utils.py +63 -4
  11. agno/db/firestore/firestore.py +435 -64
  12. agno/db/firestore/schemas.py +11 -0
  13. agno/db/firestore/utils.py +102 -4
  14. agno/db/gcs_json/gcs_json_db.py +384 -42
  15. agno/db/gcs_json/utils.py +60 -26
  16. agno/db/in_memory/in_memory_db.py +351 -66
  17. agno/db/in_memory/utils.py +60 -2
  18. agno/db/json/json_db.py +339 -48
  19. agno/db/json/utils.py +60 -26
  20. agno/db/migrations/manager.py +199 -0
  21. agno/db/migrations/v1_to_v2.py +510 -37
  22. agno/db/migrations/versions/__init__.py +0 -0
  23. agno/db/migrations/versions/v2_3_0.py +938 -0
  24. agno/db/mongo/__init__.py +15 -1
  25. agno/db/mongo/async_mongo.py +2036 -0
  26. agno/db/mongo/mongo.py +653 -76
  27. agno/db/mongo/schemas.py +13 -0
  28. agno/db/mongo/utils.py +80 -8
  29. agno/db/mysql/mysql.py +687 -25
  30. agno/db/mysql/schemas.py +61 -37
  31. agno/db/mysql/utils.py +60 -2
  32. agno/db/postgres/__init__.py +2 -1
  33. agno/db/postgres/async_postgres.py +2001 -0
  34. agno/db/postgres/postgres.py +676 -57
  35. agno/db/postgres/schemas.py +43 -18
  36. agno/db/postgres/utils.py +164 -2
  37. agno/db/redis/redis.py +344 -38
  38. agno/db/redis/schemas.py +18 -0
  39. agno/db/redis/utils.py +60 -2
  40. agno/db/schemas/__init__.py +2 -1
  41. agno/db/schemas/culture.py +120 -0
  42. agno/db/schemas/memory.py +13 -0
  43. agno/db/singlestore/schemas.py +26 -1
  44. agno/db/singlestore/singlestore.py +687 -53
  45. agno/db/singlestore/utils.py +60 -2
  46. agno/db/sqlite/__init__.py +2 -1
  47. agno/db/sqlite/async_sqlite.py +2371 -0
  48. agno/db/sqlite/schemas.py +24 -0
  49. agno/db/sqlite/sqlite.py +774 -85
  50. agno/db/sqlite/utils.py +168 -5
  51. agno/db/surrealdb/__init__.py +3 -0
  52. agno/db/surrealdb/metrics.py +292 -0
  53. agno/db/surrealdb/models.py +309 -0
  54. agno/db/surrealdb/queries.py +71 -0
  55. agno/db/surrealdb/surrealdb.py +1361 -0
  56. agno/db/surrealdb/utils.py +147 -0
  57. agno/db/utils.py +50 -22
  58. agno/eval/accuracy.py +50 -43
  59. agno/eval/performance.py +6 -3
  60. agno/eval/reliability.py +6 -3
  61. agno/eval/utils.py +33 -16
  62. agno/exceptions.py +68 -1
  63. agno/filters.py +354 -0
  64. agno/guardrails/__init__.py +6 -0
  65. agno/guardrails/base.py +19 -0
  66. agno/guardrails/openai.py +144 -0
  67. agno/guardrails/pii.py +94 -0
  68. agno/guardrails/prompt_injection.py +52 -0
  69. agno/integrations/discord/client.py +1 -0
  70. agno/knowledge/chunking/agentic.py +13 -10
  71. agno/knowledge/chunking/fixed.py +1 -1
  72. agno/knowledge/chunking/semantic.py +40 -8
  73. agno/knowledge/chunking/strategy.py +59 -15
  74. agno/knowledge/embedder/aws_bedrock.py +9 -4
  75. agno/knowledge/embedder/azure_openai.py +54 -0
  76. agno/knowledge/embedder/base.py +2 -0
  77. agno/knowledge/embedder/cohere.py +184 -5
  78. agno/knowledge/embedder/fastembed.py +1 -1
  79. agno/knowledge/embedder/google.py +79 -1
  80. agno/knowledge/embedder/huggingface.py +9 -4
  81. agno/knowledge/embedder/jina.py +63 -0
  82. agno/knowledge/embedder/mistral.py +78 -11
  83. agno/knowledge/embedder/nebius.py +1 -1
  84. agno/knowledge/embedder/ollama.py +13 -0
  85. agno/knowledge/embedder/openai.py +37 -65
  86. agno/knowledge/embedder/sentence_transformer.py +8 -4
  87. agno/knowledge/embedder/vllm.py +262 -0
  88. agno/knowledge/embedder/voyageai.py +69 -16
  89. agno/knowledge/knowledge.py +594 -186
  90. agno/knowledge/reader/base.py +9 -2
  91. agno/knowledge/reader/csv_reader.py +8 -10
  92. agno/knowledge/reader/docx_reader.py +5 -6
  93. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  94. agno/knowledge/reader/json_reader.py +6 -5
  95. agno/knowledge/reader/markdown_reader.py +13 -13
  96. agno/knowledge/reader/pdf_reader.py +43 -68
  97. agno/knowledge/reader/pptx_reader.py +101 -0
  98. agno/knowledge/reader/reader_factory.py +51 -6
  99. agno/knowledge/reader/s3_reader.py +3 -15
  100. agno/knowledge/reader/tavily_reader.py +194 -0
  101. agno/knowledge/reader/text_reader.py +13 -13
  102. agno/knowledge/reader/web_search_reader.py +2 -43
  103. agno/knowledge/reader/website_reader.py +43 -25
  104. agno/knowledge/reranker/__init__.py +2 -8
  105. agno/knowledge/types.py +9 -0
  106. agno/knowledge/utils.py +20 -0
  107. agno/media.py +72 -0
  108. agno/memory/manager.py +336 -82
  109. agno/models/aimlapi/aimlapi.py +2 -2
  110. agno/models/anthropic/claude.py +183 -37
  111. agno/models/aws/bedrock.py +52 -112
  112. agno/models/aws/claude.py +33 -1
  113. agno/models/azure/ai_foundry.py +33 -15
  114. agno/models/azure/openai_chat.py +25 -8
  115. agno/models/base.py +999 -519
  116. agno/models/cerebras/cerebras.py +19 -13
  117. agno/models/cerebras/cerebras_openai.py +8 -5
  118. agno/models/cohere/chat.py +27 -1
  119. agno/models/cometapi/__init__.py +5 -0
  120. agno/models/cometapi/cometapi.py +57 -0
  121. agno/models/dashscope/dashscope.py +1 -0
  122. agno/models/deepinfra/deepinfra.py +2 -2
  123. agno/models/deepseek/deepseek.py +2 -2
  124. agno/models/fireworks/fireworks.py +2 -2
  125. agno/models/google/gemini.py +103 -31
  126. agno/models/groq/groq.py +28 -11
  127. agno/models/huggingface/huggingface.py +2 -1
  128. agno/models/internlm/internlm.py +2 -2
  129. agno/models/langdb/langdb.py +4 -4
  130. agno/models/litellm/chat.py +18 -1
  131. agno/models/litellm/litellm_openai.py +2 -2
  132. agno/models/llama_cpp/__init__.py +5 -0
  133. agno/models/llama_cpp/llama_cpp.py +22 -0
  134. agno/models/message.py +139 -0
  135. agno/models/meta/llama.py +27 -10
  136. agno/models/meta/llama_openai.py +5 -17
  137. agno/models/nebius/nebius.py +6 -6
  138. agno/models/nexus/__init__.py +3 -0
  139. agno/models/nexus/nexus.py +22 -0
  140. agno/models/nvidia/nvidia.py +2 -2
  141. agno/models/ollama/chat.py +59 -5
  142. agno/models/openai/chat.py +69 -29
  143. agno/models/openai/responses.py +103 -106
  144. agno/models/openrouter/openrouter.py +41 -3
  145. agno/models/perplexity/perplexity.py +4 -5
  146. agno/models/portkey/portkey.py +3 -3
  147. agno/models/requesty/__init__.py +5 -0
  148. agno/models/requesty/requesty.py +52 -0
  149. agno/models/response.py +77 -1
  150. agno/models/sambanova/sambanova.py +2 -2
  151. agno/models/siliconflow/__init__.py +5 -0
  152. agno/models/siliconflow/siliconflow.py +25 -0
  153. agno/models/together/together.py +2 -2
  154. agno/models/utils.py +254 -8
  155. agno/models/vercel/v0.py +2 -2
  156. agno/models/vertexai/__init__.py +0 -0
  157. agno/models/vertexai/claude.py +96 -0
  158. agno/models/vllm/vllm.py +1 -0
  159. agno/models/xai/xai.py +3 -2
  160. agno/os/app.py +543 -178
  161. agno/os/auth.py +24 -14
  162. agno/os/config.py +1 -0
  163. agno/os/interfaces/__init__.py +1 -0
  164. agno/os/interfaces/a2a/__init__.py +3 -0
  165. agno/os/interfaces/a2a/a2a.py +42 -0
  166. agno/os/interfaces/a2a/router.py +250 -0
  167. agno/os/interfaces/a2a/utils.py +924 -0
  168. agno/os/interfaces/agui/agui.py +23 -7
  169. agno/os/interfaces/agui/router.py +27 -3
  170. agno/os/interfaces/agui/utils.py +242 -142
  171. agno/os/interfaces/base.py +6 -2
  172. agno/os/interfaces/slack/router.py +81 -23
  173. agno/os/interfaces/slack/slack.py +29 -14
  174. agno/os/interfaces/whatsapp/router.py +11 -4
  175. agno/os/interfaces/whatsapp/whatsapp.py +14 -7
  176. agno/os/mcp.py +111 -54
  177. agno/os/middleware/__init__.py +7 -0
  178. agno/os/middleware/jwt.py +233 -0
  179. agno/os/router.py +556 -139
  180. agno/os/routers/evals/evals.py +71 -34
  181. agno/os/routers/evals/schemas.py +31 -31
  182. agno/os/routers/evals/utils.py +6 -5
  183. agno/os/routers/health.py +31 -0
  184. agno/os/routers/home.py +52 -0
  185. agno/os/routers/knowledge/knowledge.py +185 -38
  186. agno/os/routers/knowledge/schemas.py +82 -22
  187. agno/os/routers/memory/memory.py +158 -53
  188. agno/os/routers/memory/schemas.py +20 -16
  189. agno/os/routers/metrics/metrics.py +20 -8
  190. agno/os/routers/metrics/schemas.py +16 -16
  191. agno/os/routers/session/session.py +499 -38
  192. agno/os/schema.py +308 -198
  193. agno/os/utils.py +401 -41
  194. agno/reasoning/anthropic.py +80 -0
  195. agno/reasoning/azure_ai_foundry.py +2 -2
  196. agno/reasoning/deepseek.py +2 -2
  197. agno/reasoning/default.py +3 -1
  198. agno/reasoning/gemini.py +73 -0
  199. agno/reasoning/groq.py +2 -2
  200. agno/reasoning/ollama.py +2 -2
  201. agno/reasoning/openai.py +7 -2
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +248 -94
  205. agno/run/base.py +44 -5
  206. agno/run/team.py +238 -97
  207. agno/run/workflow.py +144 -33
  208. agno/session/agent.py +105 -89
  209. agno/session/summary.py +65 -25
  210. agno/session/team.py +176 -96
  211. agno/session/workflow.py +406 -40
  212. agno/team/team.py +3854 -1610
  213. agno/tools/dalle.py +2 -4
  214. agno/tools/decorator.py +4 -2
  215. agno/tools/duckduckgo.py +15 -11
  216. agno/tools/e2b.py +14 -7
  217. agno/tools/eleven_labs.py +23 -25
  218. agno/tools/exa.py +21 -16
  219. agno/tools/file.py +153 -23
  220. agno/tools/file_generation.py +350 -0
  221. agno/tools/firecrawl.py +4 -4
  222. agno/tools/function.py +250 -30
  223. agno/tools/gmail.py +238 -14
  224. agno/tools/google_drive.py +270 -0
  225. agno/tools/googlecalendar.py +36 -8
  226. agno/tools/googlesheets.py +20 -5
  227. agno/tools/jira.py +20 -0
  228. agno/tools/knowledge.py +3 -3
  229. agno/tools/mcp/__init__.py +10 -0
  230. agno/tools/mcp/mcp.py +331 -0
  231. agno/tools/mcp/multi_mcp.py +347 -0
  232. agno/tools/mcp/params.py +24 -0
  233. agno/tools/mcp_toolbox.py +284 -0
  234. agno/tools/mem0.py +11 -17
  235. agno/tools/memori.py +1 -53
  236. agno/tools/memory.py +419 -0
  237. agno/tools/models/nebius.py +5 -5
  238. agno/tools/models_labs.py +20 -10
  239. agno/tools/notion.py +204 -0
  240. agno/tools/parallel.py +314 -0
  241. agno/tools/scrapegraph.py +58 -31
  242. agno/tools/searxng.py +2 -2
  243. agno/tools/serper.py +2 -2
  244. agno/tools/slack.py +18 -3
  245. agno/tools/spider.py +2 -2
  246. agno/tools/tavily.py +146 -0
  247. agno/tools/whatsapp.py +1 -1
  248. agno/tools/workflow.py +278 -0
  249. agno/tools/yfinance.py +12 -11
  250. agno/utils/agent.py +820 -0
  251. agno/utils/audio.py +27 -0
  252. agno/utils/common.py +90 -1
  253. agno/utils/events.py +217 -2
  254. agno/utils/gemini.py +180 -22
  255. agno/utils/hooks.py +57 -0
  256. agno/utils/http.py +111 -0
  257. agno/utils/knowledge.py +12 -5
  258. agno/utils/log.py +1 -0
  259. agno/utils/mcp.py +92 -2
  260. agno/utils/media.py +188 -10
  261. agno/utils/merge_dict.py +22 -1
  262. agno/utils/message.py +60 -0
  263. agno/utils/models/claude.py +40 -11
  264. agno/utils/print_response/agent.py +105 -21
  265. agno/utils/print_response/team.py +103 -38
  266. agno/utils/print_response/workflow.py +251 -34
  267. agno/utils/reasoning.py +22 -1
  268. agno/utils/serialize.py +32 -0
  269. agno/utils/streamlit.py +16 -10
  270. agno/utils/string.py +41 -0
  271. agno/utils/team.py +98 -9
  272. agno/utils/tools.py +1 -1
  273. agno/vectordb/base.py +23 -4
  274. agno/vectordb/cassandra/cassandra.py +65 -9
  275. agno/vectordb/chroma/chromadb.py +182 -38
  276. agno/vectordb/clickhouse/clickhousedb.py +64 -11
  277. agno/vectordb/couchbase/couchbase.py +105 -10
  278. agno/vectordb/lancedb/lance_db.py +124 -133
  279. agno/vectordb/langchaindb/langchaindb.py +25 -7
  280. agno/vectordb/lightrag/lightrag.py +17 -3
  281. agno/vectordb/llamaindex/__init__.py +3 -0
  282. agno/vectordb/llamaindex/llamaindexdb.py +46 -7
  283. agno/vectordb/milvus/milvus.py +126 -9
  284. agno/vectordb/mongodb/__init__.py +7 -1
  285. agno/vectordb/mongodb/mongodb.py +112 -7
  286. agno/vectordb/pgvector/pgvector.py +142 -21
  287. agno/vectordb/pineconedb/pineconedb.py +80 -8
  288. agno/vectordb/qdrant/qdrant.py +125 -39
  289. agno/vectordb/redis/__init__.py +9 -0
  290. agno/vectordb/redis/redisdb.py +694 -0
  291. agno/vectordb/singlestore/singlestore.py +111 -25
  292. agno/vectordb/surrealdb/surrealdb.py +31 -5
  293. agno/vectordb/upstashdb/upstashdb.py +76 -8
  294. agno/vectordb/weaviate/weaviate.py +86 -15
  295. agno/workflow/__init__.py +2 -0
  296. agno/workflow/agent.py +299 -0
  297. agno/workflow/condition.py +112 -18
  298. agno/workflow/loop.py +69 -10
  299. agno/workflow/parallel.py +266 -118
  300. agno/workflow/router.py +110 -17
  301. agno/workflow/step.py +638 -129
  302. agno/workflow/steps.py +65 -6
  303. agno/workflow/types.py +61 -23
  304. agno/workflow/workflow.py +2085 -272
  305. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/METADATA +182 -58
  306. agno-2.3.0.dist-info/RECORD +577 -0
  307. agno/knowledge/reader/url_reader.py +0 -128
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -610
  310. agno/utils/models/aws_claude.py +0 -170
  311. agno-2.0.1.dist-info/RECORD +0 -515
  312. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
  313. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,11 @@
1
1
  import logging
2
2
  from copy import deepcopy
3
- from typing import List, Optional
3
+ from typing import List, Optional, Union, cast
4
4
 
5
5
  from fastapi import APIRouter, Depends, HTTPException, Query
6
6
 
7
7
  from agno.agent.agent import Agent
8
- from agno.db.base import BaseDb
8
+ from agno.db.base import AsyncBaseDb, BaseDb
9
9
  from agno.db.schemas.evals import EvalFilterType, EvalType
10
10
  from agno.models.utils import get_model
11
11
  from agno.os.auth import get_authentication_dependency
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
34
34
 
35
35
 
36
36
  def get_eval_router(
37
- dbs: dict[str, BaseDb],
37
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
38
38
  agents: Optional[List[Agent]] = None,
39
39
  teams: Optional[List[Team]] = None,
40
40
  settings: AgnoAPISettings = AgnoAPISettings(),
@@ -55,7 +55,10 @@ def get_eval_router(
55
55
 
56
56
 
57
57
  def attach_routes(
58
- router: APIRouter, dbs: dict[str, BaseDb], agents: Optional[List[Agent]] = None, teams: Optional[List[Team]] = None
58
+ router: APIRouter,
59
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
60
+ agents: Optional[List[Agent]] = None,
61
+ teams: Optional[List[Team]] = None,
59
62
  ) -> APIRouter:
60
63
  @router.get(
61
64
  "/eval-runs",
@@ -112,21 +115,39 @@ def attach_routes(
112
115
  sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
113
116
  sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
114
117
  db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
118
+ table: Optional[str] = Query(default=None, description="The database table to use"),
115
119
  ) -> PaginatedResponse[EvalSchema]:
116
- db = get_db(dbs, db_id)
117
- eval_runs, total_count = db.get_eval_runs(
118
- limit=limit,
119
- page=page,
120
- sort_by=sort_by,
121
- sort_order=sort_order,
122
- agent_id=agent_id,
123
- team_id=team_id,
124
- workflow_id=workflow_id,
125
- model_id=model_id,
126
- eval_type=eval_types,
127
- filter_type=filter_type,
128
- deserialize=False,
129
- )
120
+ db = await get_db(dbs, db_id, table)
121
+
122
+ if isinstance(db, AsyncBaseDb):
123
+ db = cast(AsyncBaseDb, db)
124
+ eval_runs, total_count = await db.get_eval_runs(
125
+ limit=limit,
126
+ page=page,
127
+ sort_by=sort_by,
128
+ sort_order=sort_order,
129
+ agent_id=agent_id,
130
+ team_id=team_id,
131
+ workflow_id=workflow_id,
132
+ model_id=model_id,
133
+ eval_type=eval_types,
134
+ filter_type=filter_type,
135
+ deserialize=False,
136
+ )
137
+ else:
138
+ eval_runs, total_count = db.get_eval_runs( # type: ignore
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
+ )
130
151
 
131
152
  return PaginatedResponse(
132
153
  data=[EvalSchema.from_dict(eval_run) for eval_run in eval_runs], # type: ignore
@@ -178,9 +199,14 @@ def attach_routes(
178
199
  async def get_eval_run(
179
200
  eval_run_id: str,
180
201
  db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
202
+ table: Optional[str] = Query(default=None, description="Table to query eval run from"),
181
203
  ) -> EvalSchema:
182
- db = get_db(dbs, db_id)
183
- eval_run = db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
204
+ db = await get_db(dbs, db_id, table)
205
+ if isinstance(db, AsyncBaseDb):
206
+ db = cast(AsyncBaseDb, db)
207
+ eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
208
+ else:
209
+ eval_run = db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
184
210
  if not eval_run:
185
211
  raise HTTPException(status_code=404, detail=f"Eval run with id '{eval_run_id}' not found")
186
212
 
@@ -200,10 +226,15 @@ def attach_routes(
200
226
  async def delete_eval_runs(
201
227
  request: DeleteEvalRunsRequest,
202
228
  db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
229
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
203
230
  ) -> None:
204
231
  try:
205
- db = get_db(dbs, db_id)
206
- db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
232
+ db = await get_db(dbs, db_id, table)
233
+ if isinstance(db, AsyncBaseDb):
234
+ db = cast(AsyncBaseDb, db)
235
+ await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
236
+ else:
237
+ db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
207
238
  except Exception as e:
208
239
  raise HTTPException(status_code=500, detail=f"Failed to delete eval runs: {e}")
209
240
 
@@ -249,10 +280,15 @@ def attach_routes(
249
280
  eval_run_id: str,
250
281
  request: UpdateEvalRunRequest,
251
282
  db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
283
+ table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
252
284
  ) -> EvalSchema:
253
285
  try:
254
- db = get_db(dbs, db_id)
255
- eval_run = db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
286
+ db = await get_db(dbs, db_id, table)
287
+ if isinstance(db, AsyncBaseDb):
288
+ db = cast(AsyncBaseDb, db)
289
+ eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
290
+ else:
291
+ eval_run = db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
256
292
  except Exception as e:
257
293
  raise HTTPException(status_code=500, detail=f"Failed to rename eval run: {e}")
258
294
 
@@ -304,8 +340,9 @@ def attach_routes(
304
340
  async def run_eval(
305
341
  eval_run_input: EvalRunInput,
306
342
  db_id: Optional[str] = Query(default=None, description="Database ID to use for evaluation"),
343
+ table: Optional[str] = Query(default=None, description="Table to use for evaluation"),
307
344
  ) -> Optional[EvalSchema]:
308
- db = get_db(dbs, db_id)
345
+ db = await get_db(dbs, db_id, table)
309
346
 
310
347
  if eval_run_input.agent_id and eval_run_input.team_id:
311
348
  raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
@@ -324,10 +361,10 @@ def attach_routes(
324
361
  ):
325
362
  default_model = deepcopy(agent.model)
326
363
  if eval_run_input.model_id != agent.model.id or eval_run_input.model_provider != agent.model.provider:
327
- model = get_model(
328
- model_id=eval_run_input.model_id.lower(),
329
- model_provider=eval_run_input.model_provider.lower(),
330
- )
364
+ model_provider = eval_run_input.model_provider.lower()
365
+ model_id = eval_run_input.model_id.lower()
366
+ model_string = f"{model_provider}:{model_id}"
367
+ model = get_model(model_string)
331
368
  agent.model = model
332
369
 
333
370
  team = None
@@ -346,10 +383,10 @@ def attach_routes(
346
383
  ):
347
384
  default_model = deepcopy(team.model)
348
385
  if eval_run_input.model_id != team.model.id or eval_run_input.model_provider != team.model.provider:
349
- model = get_model(
350
- model_id=eval_run_input.model_id.lower(),
351
- model_provider=eval_run_input.model_provider.lower(),
352
- )
386
+ model_provider = eval_run_input.model_provider.lower()
387
+ model_id = eval_run_input.model_id.lower()
388
+ model_string = f"{model_provider}:{model_id}"
389
+ model = get_model(model_string)
353
390
  team.model = model
354
391
 
355
392
  agent = None
@@ -380,7 +417,7 @@ def parse_eval_types_filter(
380
417
  eval_types: Optional[str] = Query(
381
418
  default=None,
382
419
  description="Comma-separated eval types (accuracy,performance,reliability)",
383
- example="accuracy,performance",
420
+ examples=["accuracy,performance"],
384
421
  ),
385
422
  ) -> Optional[List[EvalType]]:
386
423
  """Parse comma-separated eval types into EvalType enums for filtering evaluation runs."""
@@ -2,7 +2,7 @@ from dataclasses import asdict
2
2
  from datetime import datetime, timezone
3
3
  from typing import Any, Dict, List, Optional
4
4
 
5
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, Field
6
6
 
7
7
  from agno.db.schemas.evals import EvalType
8
8
  from agno.eval import AccuracyResult, PerformanceResult, ReliabilityResult
@@ -12,43 +12,43 @@ from agno.eval.reliability import ReliabilityEval
12
12
 
13
13
 
14
14
  class EvalRunInput(BaseModel):
15
- agent_id: Optional[str] = None
16
- team_id: Optional[str] = None
17
-
18
- model_id: Optional[str] = None
19
- model_provider: Optional[str] = None
20
- eval_type: EvalType
21
- input: str
22
- additional_guidelines: Optional[str] = None
23
- additional_context: Optional[str] = None
24
- num_iterations: Optional[int] = 1
25
- name: Optional[str] = None
15
+ agent_id: Optional[str] = Field(None, description="Agent ID to evaluate")
16
+ team_id: Optional[str] = Field(None, description="Team ID to evaluate")
17
+
18
+ model_id: Optional[str] = Field(None, description="Model ID to use for evaluation")
19
+ model_provider: Optional[str] = Field(None, description="Model provider name")
20
+ eval_type: EvalType = Field(..., description="Type of evaluation to run (accuracy, performance, or reliability)")
21
+ input: str = Field(..., description="Input text/query for the evaluation", min_length=1)
22
+ additional_guidelines: Optional[str] = Field(None, description="Additional guidelines for the evaluation")
23
+ additional_context: Optional[str] = Field(None, description="Additional context for the evaluation")
24
+ num_iterations: int = Field(1, description="Number of times to run the evaluation", ge=1, le=100)
25
+ name: Optional[str] = Field(None, description="Name for this evaluation run")
26
26
 
27
27
  # Accuracy eval specific fields
28
- expected_output: Optional[str] = None
28
+ expected_output: Optional[str] = Field(None, description="Expected output for accuracy evaluation")
29
29
 
30
30
  # Performance eval specific fields
31
- warmup_runs: Optional[int] = 0
31
+ warmup_runs: int = Field(0, description="Number of warmup runs before measuring performance", ge=0, le=10)
32
32
 
33
33
  # Reliability eval specific fields
34
- expected_tool_calls: Optional[List[str]] = None
34
+ expected_tool_calls: Optional[List[str]] = Field(None, description="Expected tool calls for reliability evaluation")
35
35
 
36
36
 
37
37
  class EvalSchema(BaseModel):
38
- id: str
39
-
40
- agent_id: Optional[str] = None
41
- model_id: Optional[str] = None
42
- model_provider: Optional[str] = None
43
- team_id: Optional[str] = None
44
- workflow_id: Optional[str] = None
45
- name: Optional[str] = None
46
- evaluated_component_name: Optional[str] = None
47
- eval_type: EvalType
48
- eval_data: Dict[str, Any]
49
- eval_input: Optional[Dict[str, Any]] = None
50
- created_at: Optional[datetime] = None
51
- updated_at: Optional[datetime] = None
38
+ id: str = Field(..., description="Unique identifier for the evaluation run")
39
+
40
+ agent_id: Optional[str] = Field(None, description="Agent ID that was evaluated")
41
+ model_id: Optional[str] = Field(None, description="Model ID used in evaluation")
42
+ model_provider: Optional[str] = Field(None, description="Model provider name")
43
+ team_id: Optional[str] = Field(None, description="Team ID that was evaluated")
44
+ workflow_id: Optional[str] = Field(None, description="Workflow ID that was evaluated")
45
+ name: Optional[str] = Field(None, description="Name of the evaluation run")
46
+ evaluated_component_name: Optional[str] = Field(None, description="Name of the evaluated component")
47
+ eval_type: EvalType = Field(..., description="Type of evaluation (accuracy, performance, or reliability)")
48
+ eval_data: Dict[str, Any] = Field(..., description="Evaluation results and metrics")
49
+ eval_input: Optional[Dict[str, Any]] = Field(None, description="Input parameters used for the evaluation")
50
+ created_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was created")
51
+ updated_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was last updated")
52
52
 
53
53
  @classmethod
54
54
  def from_dict(cls, eval_run: Dict[str, Any]) -> "EvalSchema":
@@ -135,8 +135,8 @@ class EvalSchema(BaseModel):
135
135
 
136
136
 
137
137
  class DeleteEvalRunsRequest(BaseModel):
138
- eval_run_ids: List[str]
138
+ eval_run_ids: List[str] = Field(..., description="List of evaluation run IDs to delete", min_length=1)
139
139
 
140
140
 
141
141
  class UpdateEvalRunRequest(BaseModel):
142
- name: str
142
+ name: str = Field(..., description="New name for the evaluation run", min_length=1, max_length=255)
@@ -1,9 +1,9 @@
1
- from typing import Optional
1
+ from typing import Optional, Union
2
2
 
3
3
  from fastapi import HTTPException
4
4
 
5
5
  from agno.agent.agent import Agent
6
- from agno.db.base import BaseDb
6
+ from agno.db.base import AsyncBaseDb, BaseDb
7
7
  from agno.eval.accuracy import AccuracyEval
8
8
  from agno.eval.performance import PerformanceEval
9
9
  from agno.eval.reliability import ReliabilityEval
@@ -14,7 +14,7 @@ from agno.team.team import Team
14
14
 
15
15
  async def run_accuracy_eval(
16
16
  eval_run_input: EvalRunInput,
17
- db: BaseDb,
17
+ db: Union[BaseDb, AsyncBaseDb],
18
18
  agent: Optional[Agent] = None,
19
19
  team: Optional[Team] = None,
20
20
  default_model: Optional[Model] = None,
@@ -33,6 +33,7 @@ async def run_accuracy_eval(
33
33
  additional_context=eval_run_input.additional_context,
34
34
  num_iterations=eval_run_input.num_iterations or 1,
35
35
  name=eval_run_input.name,
36
+ model=default_model,
36
37
  )
37
38
 
38
39
  result = accuracy_eval.run(print_results=False, print_summary=False)
@@ -52,7 +53,7 @@ async def run_accuracy_eval(
52
53
 
53
54
  async def run_performance_eval(
54
55
  eval_run_input: EvalRunInput,
55
- db: BaseDb,
56
+ db: Union[BaseDb, AsyncBaseDb],
56
57
  agent: Optional[Agent] = None,
57
58
  team: Optional[Team] = None,
58
59
  default_model: Optional[Model] = None,
@@ -109,7 +110,7 @@ async def run_performance_eval(
109
110
 
110
111
  async def run_reliability_eval(
111
112
  eval_run_input: EvalRunInput,
112
- db: BaseDb,
113
+ db: Union[BaseDb, AsyncBaseDb],
113
114
  agent: Optional[Agent] = None,
114
115
  team: Optional[Team] = None,
115
116
  default_model: Optional[Model] = None,
@@ -0,0 +1,31 @@
1
+ from datetime import datetime, timezone
2
+
3
+ from fastapi import APIRouter
4
+
5
+ from agno.os.schema import HealthResponse
6
+
7
+
8
+ def get_health_router(health_endpoint: str = "/health") -> APIRouter:
9
+ router = APIRouter(tags=["Health"])
10
+
11
+ started_time_stamp = datetime.now(timezone.utc).timestamp()
12
+
13
+ @router.get(
14
+ health_endpoint,
15
+ operation_id="health_check",
16
+ summary="Health Check",
17
+ description="Check the health status of the AgentOS API. Returns a simple status indicator.",
18
+ response_model=HealthResponse,
19
+ responses={
20
+ 200: {
21
+ "description": "API is healthy and operational",
22
+ "content": {
23
+ "application/json": {"example": {"status": "ok", "instantiated_at": str(started_time_stamp)}}
24
+ },
25
+ }
26
+ },
27
+ )
28
+ async def health_check() -> HealthResponse:
29
+ return HealthResponse(status="ok", instantiated_at=str(started_time_stamp))
30
+
31
+ return router
@@ -0,0 +1,52 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from fastapi import APIRouter
4
+
5
+ if TYPE_CHECKING:
6
+ from agno.os.app import AgentOS
7
+
8
+
9
+ def get_home_router(os: "AgentOS") -> APIRouter:
10
+ router = APIRouter(tags=["Home"])
11
+
12
+ @router.get(
13
+ "/",
14
+ operation_id="get_api_info",
15
+ summary="API Information",
16
+ description=(
17
+ "Get basic information about this AgentOS API instance, including:\n\n"
18
+ "- API metadata and version\n"
19
+ "- Available capabilities overview\n"
20
+ "- Links to key endpoints and documentation"
21
+ ),
22
+ responses={
23
+ 200: {
24
+ "description": "API information retrieved successfully",
25
+ "content": {
26
+ "application/json": {
27
+ "examples": {
28
+ "home": {
29
+ "summary": "Example home response",
30
+ "value": {
31
+ "name": "AgentOS API",
32
+ "description": "AI Agent Operating System API",
33
+ "id": "demo-os",
34
+ "version": "1.0.0",
35
+ },
36
+ }
37
+ }
38
+ }
39
+ },
40
+ }
41
+ },
42
+ )
43
+ async def get_api_info():
44
+ """Get basic API information and available capabilities"""
45
+ return {
46
+ "name": "AgentOS API",
47
+ "description": os.description or "AI Agent Operating System API",
48
+ "id": os.id or "agno-agentos",
49
+ "version": os.version or "1.0.0",
50
+ }
51
+
52
+ return router