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
@@ -0,0 +1,3 @@
1
+ from agno.db.postgres import AsyncPostgresDb
2
+
3
+ __all__ = ["AsyncPostgresDb"]
agno/db/base.py CHANGED
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
5
5
  from uuid import uuid4
6
6
 
7
7
  from agno.db.schemas import UserMemory
8
+ from agno.db.schemas.culture import CulturalKnowledge
8
9
  from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
9
10
  from agno.db.schemas.knowledge import KnowledgeRow
10
11
  from agno.session import Session
@@ -17,21 +18,48 @@ class SessionType(str, Enum):
17
18
 
18
19
 
19
20
  class BaseDb(ABC):
21
+ """Base abstract class for all our Database implementations."""
22
+
23
+ # We assume the database to be up to date with the 2.0.0 release
24
+ default_schema_version = "2.0.0"
25
+
20
26
  def __init__(
21
27
  self,
22
28
  session_table: Optional[str] = None,
29
+ culture_table: Optional[str] = None,
23
30
  memory_table: Optional[str] = None,
24
31
  metrics_table: Optional[str] = None,
25
32
  eval_table: Optional[str] = None,
26
33
  knowledge_table: Optional[str] = None,
34
+ versions_table: Optional[str] = None,
27
35
  id: Optional[str] = None,
28
36
  ):
29
37
  self.id = id or str(uuid4())
30
38
  self.session_table_name = session_table or "agno_sessions"
39
+ self.culture_table_name = culture_table or "agno_culture"
31
40
  self.memory_table_name = memory_table or "agno_memories"
32
41
  self.metrics_table_name = metrics_table or "agno_metrics"
33
42
  self.eval_table_name = eval_table or "agno_eval_runs"
34
43
  self.knowledge_table_name = knowledge_table or "agno_knowledge"
44
+ self.versions_table_name = versions_table or "agno_schema_versions"
45
+
46
+ @abstractmethod
47
+ def table_exists(self, table_name: str) -> bool:
48
+ raise NotImplementedError
49
+
50
+ def _create_all_tables(self) -> None:
51
+ """Create all tables for this database."""
52
+ pass
53
+
54
+ # --- Schema Version ---
55
+ @abstractmethod
56
+ def get_latest_schema_version(self, table_name: str):
57
+ raise NotImplementedError
58
+
59
+ @abstractmethod
60
+ def upsert_schema_version(self, table_name: str, version: str):
61
+ """Upsert the schema version into the database."""
62
+ raise NotImplementedError
35
63
 
36
64
  # --- Sessions ---
37
65
  @abstractmethod
@@ -71,7 +99,11 @@ class BaseDb(ABC):
71
99
 
72
100
  @abstractmethod
73
101
  def rename_session(
74
- self, session_id: str, session_type: SessionType, session_name: str, deserialize: Optional[bool] = True
102
+ self,
103
+ session_id: str,
104
+ session_type: SessionType,
105
+ session_name: str,
106
+ deserialize: Optional[bool] = True,
75
107
  ) -> Optional[Union[Session, Dict[str, Any]]]:
76
108
  raise NotImplementedError
77
109
 
@@ -81,27 +113,39 @@ class BaseDb(ABC):
81
113
  ) -> Optional[Union[Session, Dict[str, Any]]]:
82
114
  raise NotImplementedError
83
115
 
84
- # --- Memory ---
116
+ @abstractmethod
117
+ def upsert_sessions(
118
+ self,
119
+ sessions: List[Session],
120
+ deserialize: Optional[bool] = True,
121
+ preserve_updated_at: bool = False,
122
+ ) -> List[Union[Session, Dict[str, Any]]]:
123
+ """Bulk upsert multiple sessions for improved performance on large datasets."""
124
+ raise NotImplementedError
85
125
 
126
+ # --- Memory ---
86
127
  @abstractmethod
87
128
  def clear_memories(self) -> None:
88
129
  raise NotImplementedError
89
130
 
90
131
  @abstractmethod
91
- def delete_user_memory(self, memory_id: str) -> None:
132
+ def delete_user_memory(self, memory_id: str, user_id: Optional[str] = None) -> None:
92
133
  raise NotImplementedError
93
134
 
94
135
  @abstractmethod
95
- def delete_user_memories(self, memory_ids: List[str]) -> None:
136
+ def delete_user_memories(self, memory_ids: List[str], user_id: Optional[str] = None) -> None:
96
137
  raise NotImplementedError
97
138
 
98
139
  @abstractmethod
99
- def get_all_memory_topics(self) -> List[str]:
140
+ def get_all_memory_topics(self, user_id: Optional[str] = None) -> List[str]:
100
141
  raise NotImplementedError
101
142
 
102
143
  @abstractmethod
103
144
  def get_user_memory(
104
- self, memory_id: str, deserialize: Optional[bool] = True
145
+ self,
146
+ memory_id: str,
147
+ deserialize: Optional[bool] = True,
148
+ user_id: Optional[str] = None,
105
149
  ) -> Optional[Union[UserMemory, Dict[str, Any]]]:
106
150
  raise NotImplementedError
107
151
 
@@ -126,6 +170,7 @@ class BaseDb(ABC):
126
170
  self,
127
171
  limit: Optional[int] = None,
128
172
  page: Optional[int] = None,
173
+ user_id: Optional[str] = None,
129
174
  ) -> Tuple[List[Dict[str, Any]], int]:
130
175
  raise NotImplementedError
131
176
 
@@ -135,6 +180,16 @@ class BaseDb(ABC):
135
180
  ) -> Optional[Union[UserMemory, Dict[str, Any]]]:
136
181
  raise NotImplementedError
137
182
 
183
+ @abstractmethod
184
+ def upsert_memories(
185
+ self,
186
+ memories: List[UserMemory],
187
+ deserialize: Optional[bool] = True,
188
+ preserve_updated_at: bool = False,
189
+ ) -> List[Union[UserMemory, Dict[str, Any]]]:
190
+ """Bulk upsert multiple memories for improved performance on large datasets."""
191
+ raise NotImplementedError
192
+
138
193
  # --- Metrics ---
139
194
  @abstractmethod
140
195
  def get_metrics(
@@ -243,3 +298,327 @@ class BaseDb(ABC):
243
298
  self, eval_run_id: str, name: str, deserialize: Optional[bool] = True
244
299
  ) -> Optional[Union[EvalRunRecord, Dict[str, Any]]]:
245
300
  raise NotImplementedError
301
+
302
+ # --- Cultural Knowledge ---
303
+ @abstractmethod
304
+ def clear_cultural_knowledge(self) -> None:
305
+ raise NotImplementedError
306
+
307
+ @abstractmethod
308
+ def delete_cultural_knowledge(self, id: str) -> None:
309
+ raise NotImplementedError
310
+
311
+ @abstractmethod
312
+ def get_cultural_knowledge(self, id: str) -> Optional[CulturalKnowledge]:
313
+ raise NotImplementedError
314
+
315
+ @abstractmethod
316
+ def get_all_cultural_knowledge(
317
+ self,
318
+ name: Optional[str] = None,
319
+ limit: Optional[int] = None,
320
+ page: Optional[int] = None,
321
+ sort_by: Optional[str] = None,
322
+ sort_order: Optional[str] = None,
323
+ agent_id: Optional[str] = None,
324
+ team_id: Optional[str] = None,
325
+ ) -> Optional[List[CulturalKnowledge]]:
326
+ raise NotImplementedError
327
+
328
+ @abstractmethod
329
+ def upsert_cultural_knowledge(self, cultural_knowledge: CulturalKnowledge) -> Optional[CulturalKnowledge]:
330
+ raise NotImplementedError
331
+
332
+
333
+ class AsyncBaseDb(ABC):
334
+ """Base abstract class for all our async database implementations."""
335
+
336
+ def __init__(
337
+ self,
338
+ id: Optional[str] = None,
339
+ session_table: Optional[str] = None,
340
+ memory_table: Optional[str] = None,
341
+ metrics_table: Optional[str] = None,
342
+ eval_table: Optional[str] = None,
343
+ knowledge_table: Optional[str] = None,
344
+ culture_table: Optional[str] = None,
345
+ versions_table: Optional[str] = None,
346
+ ):
347
+ self.id = id or str(uuid4())
348
+ self.session_table_name = session_table or "agno_sessions"
349
+ self.memory_table_name = memory_table or "agno_memories"
350
+ self.metrics_table_name = metrics_table or "agno_metrics"
351
+ self.eval_table_name = eval_table or "agno_eval_runs"
352
+ self.knowledge_table_name = knowledge_table or "agno_knowledge"
353
+ self.culture_table_name = culture_table or "agno_culture"
354
+ self.versions_table_name = versions_table or "agno_schema_versions"
355
+
356
+ @abstractmethod
357
+ async def table_exists(self, table_name: str) -> bool:
358
+ """Check if a table with the given name exists in this database.
359
+
360
+ Default implementation returns True if the table name is configured.
361
+ Subclasses should override this to perform actual existence checks.
362
+
363
+ Args:
364
+ table_name: Name of the table to check
365
+
366
+ Returns:
367
+ bool: True if the table exists, False otherwise
368
+ """
369
+ raise NotImplementedError
370
+
371
+ @abstractmethod
372
+ async def get_latest_schema_version(self, table_name: str) -> str:
373
+ raise NotImplementedError
374
+
375
+ @abstractmethod
376
+ async def upsert_schema_version(self, table_name: str, version: str):
377
+ """Upsert the schema version into the database."""
378
+ raise NotImplementedError
379
+
380
+ # --- Sessions ---
381
+ @abstractmethod
382
+ async def delete_session(self, session_id: str) -> bool:
383
+ raise NotImplementedError
384
+
385
+ @abstractmethod
386
+ async def delete_sessions(self, session_ids: List[str]) -> None:
387
+ raise NotImplementedError
388
+
389
+ @abstractmethod
390
+ async def get_session(
391
+ self,
392
+ session_id: str,
393
+ session_type: SessionType,
394
+ user_id: Optional[str] = None,
395
+ deserialize: Optional[bool] = True,
396
+ ) -> Optional[Union[Session, Dict[str, Any]]]:
397
+ raise NotImplementedError
398
+
399
+ @abstractmethod
400
+ async def get_sessions(
401
+ self,
402
+ session_type: SessionType,
403
+ user_id: Optional[str] = None,
404
+ component_id: Optional[str] = None,
405
+ session_name: Optional[str] = None,
406
+ start_timestamp: Optional[int] = None,
407
+ end_timestamp: Optional[int] = None,
408
+ limit: Optional[int] = None,
409
+ page: Optional[int] = None,
410
+ sort_by: Optional[str] = None,
411
+ sort_order: Optional[str] = None,
412
+ deserialize: Optional[bool] = True,
413
+ ) -> Union[List[Session], Tuple[List[Dict[str, Any]], int]]:
414
+ raise NotImplementedError
415
+
416
+ @abstractmethod
417
+ async def rename_session(
418
+ self,
419
+ session_id: str,
420
+ session_type: SessionType,
421
+ session_name: str,
422
+ deserialize: Optional[bool] = True,
423
+ ) -> Optional[Union[Session, Dict[str, Any]]]:
424
+ raise NotImplementedError
425
+
426
+ @abstractmethod
427
+ async def upsert_session(
428
+ self, session: Session, deserialize: Optional[bool] = True
429
+ ) -> Optional[Union[Session, Dict[str, Any]]]:
430
+ raise NotImplementedError
431
+
432
+ # --- Memory ---
433
+ @abstractmethod
434
+ async def clear_memories(self) -> None:
435
+ raise NotImplementedError
436
+
437
+ @abstractmethod
438
+ async def delete_user_memory(self, memory_id: str, user_id: Optional[str] = None) -> None:
439
+ raise NotImplementedError
440
+
441
+ @abstractmethod
442
+ async def delete_user_memories(self, memory_ids: List[str], user_id: Optional[str] = None) -> None:
443
+ raise NotImplementedError
444
+
445
+ @abstractmethod
446
+ async def get_all_memory_topics(self, user_id: Optional[str] = None) -> List[str]:
447
+ raise NotImplementedError
448
+
449
+ @abstractmethod
450
+ async def get_user_memory(
451
+ self,
452
+ memory_id: str,
453
+ deserialize: Optional[bool] = True,
454
+ user_id: Optional[str] = None,
455
+ ) -> Optional[Union[UserMemory, Dict[str, Any]]]:
456
+ raise NotImplementedError
457
+
458
+ @abstractmethod
459
+ async def get_user_memories(
460
+ self,
461
+ user_id: Optional[str] = None,
462
+ agent_id: Optional[str] = None,
463
+ team_id: Optional[str] = None,
464
+ topics: Optional[List[str]] = None,
465
+ search_content: Optional[str] = None,
466
+ limit: Optional[int] = None,
467
+ page: Optional[int] = None,
468
+ sort_by: Optional[str] = None,
469
+ sort_order: Optional[str] = None,
470
+ deserialize: Optional[bool] = True,
471
+ ) -> Union[List[UserMemory], Tuple[List[Dict[str, Any]], int]]:
472
+ raise NotImplementedError
473
+
474
+ @abstractmethod
475
+ async def get_user_memory_stats(
476
+ self,
477
+ limit: Optional[int] = None,
478
+ page: Optional[int] = None,
479
+ user_id: Optional[str] = None,
480
+ ) -> Tuple[List[Dict[str, Any]], int]:
481
+ raise NotImplementedError
482
+
483
+ @abstractmethod
484
+ async def upsert_user_memory(
485
+ self, memory: UserMemory, deserialize: Optional[bool] = True
486
+ ) -> Optional[Union[UserMemory, Dict[str, Any]]]:
487
+ raise NotImplementedError
488
+
489
+ # --- Metrics ---
490
+ @abstractmethod
491
+ async def get_metrics(
492
+ self, starting_date: Optional[date] = None, ending_date: Optional[date] = None
493
+ ) -> Tuple[List[Dict[str, Any]], Optional[int]]:
494
+ raise NotImplementedError
495
+
496
+ @abstractmethod
497
+ async def calculate_metrics(self) -> Optional[Any]:
498
+ raise NotImplementedError
499
+
500
+ # --- Knowledge ---
501
+ @abstractmethod
502
+ async def delete_knowledge_content(self, id: str):
503
+ """Delete a knowledge row from the database.
504
+
505
+ Args:
506
+ id (str): The ID of the knowledge row to delete.
507
+ """
508
+ raise NotImplementedError
509
+
510
+ @abstractmethod
511
+ async def get_knowledge_content(self, id: str) -> Optional[KnowledgeRow]:
512
+ """Get a knowledge row from the database.
513
+
514
+ Args:
515
+ id (str): The ID of the knowledge row to get.
516
+
517
+ Returns:
518
+ Optional[KnowledgeRow]: The knowledge row, or None if it doesn't exist.
519
+ """
520
+ raise NotImplementedError
521
+
522
+ @abstractmethod
523
+ async def get_knowledge_contents(
524
+ self,
525
+ limit: Optional[int] = None,
526
+ page: Optional[int] = None,
527
+ sort_by: Optional[str] = None,
528
+ sort_order: Optional[str] = None,
529
+ ) -> Tuple[List[KnowledgeRow], int]:
530
+ """Get all knowledge contents from the database.
531
+
532
+ Args:
533
+ limit (Optional[int]): The maximum number of knowledge contents to return.
534
+ page (Optional[int]): The page number.
535
+ sort_by (Optional[str]): The column to sort by.
536
+ sort_order (Optional[str]): The order to sort by.
537
+
538
+ Returns:
539
+ Tuple[List[KnowledgeRow], int]: The knowledge contents and total count.
540
+
541
+ Raises:
542
+ Exception: If an error occurs during retrieval.
543
+ """
544
+ raise NotImplementedError
545
+
546
+ @abstractmethod
547
+ async def upsert_knowledge_content(self, knowledge_row: KnowledgeRow):
548
+ """Upsert knowledge content in the database.
549
+
550
+ Args:
551
+ knowledge_row (KnowledgeRow): The knowledge row to upsert.
552
+
553
+ Returns:
554
+ Optional[KnowledgeRow]: The upserted knowledge row, or None if the operation fails.
555
+ """
556
+ raise NotImplementedError
557
+
558
+ # --- Evals ---
559
+ @abstractmethod
560
+ async def create_eval_run(self, eval_run: EvalRunRecord) -> Optional[EvalRunRecord]:
561
+ raise NotImplementedError
562
+
563
+ @abstractmethod
564
+ async def delete_eval_runs(self, eval_run_ids: List[str]) -> None:
565
+ raise NotImplementedError
566
+
567
+ @abstractmethod
568
+ async def get_eval_run(
569
+ self, eval_run_id: str, deserialize: Optional[bool] = True
570
+ ) -> Optional[Union[EvalRunRecord, Dict[str, Any]]]:
571
+ raise NotImplementedError
572
+
573
+ @abstractmethod
574
+ async def get_eval_runs(
575
+ self,
576
+ limit: Optional[int] = None,
577
+ page: Optional[int] = None,
578
+ sort_by: Optional[str] = None,
579
+ sort_order: Optional[str] = None,
580
+ agent_id: Optional[str] = None,
581
+ team_id: Optional[str] = None,
582
+ workflow_id: Optional[str] = None,
583
+ model_id: Optional[str] = None,
584
+ filter_type: Optional[EvalFilterType] = None,
585
+ eval_type: Optional[List[EvalType]] = None,
586
+ deserialize: Optional[bool] = True,
587
+ ) -> Union[List[EvalRunRecord], Tuple[List[Dict[str, Any]], int]]:
588
+ raise NotImplementedError
589
+
590
+ @abstractmethod
591
+ async def rename_eval_run(
592
+ self, eval_run_id: str, name: str, deserialize: Optional[bool] = True
593
+ ) -> Optional[Union[EvalRunRecord, Dict[str, Any]]]:
594
+ raise NotImplementedError
595
+
596
+ # --- Cultural Notions ---
597
+ @abstractmethod
598
+ async def clear_cultural_knowledge(self) -> None:
599
+ raise NotImplementedError
600
+
601
+ @abstractmethod
602
+ async def delete_cultural_knowledge(self, id: str) -> None:
603
+ raise NotImplementedError
604
+
605
+ @abstractmethod
606
+ async def get_cultural_knowledge(self, id: str) -> Optional[CulturalKnowledge]:
607
+ raise NotImplementedError
608
+
609
+ @abstractmethod
610
+ async def get_all_cultural_knowledge(
611
+ self,
612
+ name: Optional[str] = None,
613
+ limit: Optional[int] = None,
614
+ page: Optional[int] = None,
615
+ sort_by: Optional[str] = None,
616
+ sort_order: Optional[str] = None,
617
+ agent_id: Optional[str] = None,
618
+ team_id: Optional[str] = None,
619
+ ) -> Optional[List[CulturalKnowledge]]:
620
+ raise NotImplementedError
621
+
622
+ @abstractmethod
623
+ async def upsert_cultural_knowledge(self, cultural_knowledge: CulturalKnowledge) -> Optional[CulturalKnowledge]:
624
+ raise NotImplementedError