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
agno/db/dynamo/schemas.py CHANGED
@@ -73,6 +73,8 @@ USER_MEMORY_TABLE_SCHEMA = {
73
73
  {"AttributeName": "user_id", "AttributeType": "S"},
74
74
  {"AttributeName": "agent_id", "AttributeType": "S"},
75
75
  {"AttributeName": "team_id", "AttributeType": "S"},
76
+ {"AttributeName": "workflow_id", "AttributeType": "S"},
77
+ {"AttributeName": "created_at", "AttributeType": "S"},
76
78
  {"AttributeName": "updated_at", "AttributeType": "S"},
77
79
  ],
78
80
  "GlobalSecondaryIndexes": [
@@ -123,7 +125,6 @@ EVAL_TABLE_SCHEMA = {
123
125
  "AttributeDefinitions": [
124
126
  {"AttributeName": "run_id", "AttributeType": "S"},
125
127
  {"AttributeName": "eval_type", "AttributeType": "S"},
126
- {"AttributeName": "eval_input", "AttributeType": "S"},
127
128
  {"AttributeName": "agent_id", "AttributeType": "S"},
128
129
  {"AttributeName": "team_id", "AttributeType": "S"},
129
130
  {"AttributeName": "workflow_id", "AttributeType": "S"},
@@ -176,18 +177,10 @@ KNOWLEDGE_TABLE_SCHEMA = {
176
177
  "KeySchema": [{"AttributeName": "id", "KeyType": "HASH"}],
177
178
  "AttributeDefinitions": [
178
179
  {"AttributeName": "id", "AttributeType": "S"},
179
- {"AttributeName": "name", "AttributeType": "S"},
180
- {"AttributeName": "description", "AttributeType": "S"},
181
- {"AttributeName": "metadata", "AttributeType": "S"},
180
+ {"AttributeName": "user_id", "AttributeType": "S"},
182
181
  {"AttributeName": "type", "AttributeType": "S"},
183
- {"AttributeName": "size", "AttributeType": "N"},
184
- {"AttributeName": "linked_to", "AttributeType": "S"},
185
- {"AttributeName": "access_count", "AttributeType": "N"},
186
182
  {"AttributeName": "status", "AttributeType": "S"},
187
- {"AttributeName": "status_message", "AttributeType": "S"},
188
183
  {"AttributeName": "created_at", "AttributeType": "N"},
189
- {"AttributeName": "updated_at", "AttributeType": "N"},
190
- {"AttributeName": "external_id", "AttributeType": "S"},
191
184
  ],
192
185
  "GlobalSecondaryIndexes": [
193
186
  {
@@ -252,6 +245,49 @@ METRICS_TABLE_SCHEMA = {
252
245
  "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
253
246
  }
254
247
 
248
+ CULTURAL_KNOWLEDGE_TABLE_SCHEMA = {
249
+ "TableName": "agno_cultural_knowledge",
250
+ "KeySchema": [{"AttributeName": "id", "KeyType": "HASH"}],
251
+ "AttributeDefinitions": [
252
+ {"AttributeName": "id", "AttributeType": "S"},
253
+ {"AttributeName": "name", "AttributeType": "S"},
254
+ {"AttributeName": "agent_id", "AttributeType": "S"},
255
+ {"AttributeName": "team_id", "AttributeType": "S"},
256
+ {"AttributeName": "created_at", "AttributeType": "N"},
257
+ ],
258
+ "GlobalSecondaryIndexes": [
259
+ {
260
+ "IndexName": "name-created_at-index",
261
+ "KeySchema": [
262
+ {"AttributeName": "name", "KeyType": "HASH"},
263
+ {"AttributeName": "created_at", "KeyType": "RANGE"},
264
+ ],
265
+ "Projection": {"ProjectionType": "ALL"},
266
+ "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
267
+ },
268
+ {
269
+ "IndexName": "agent_id-created_at-index",
270
+ "KeySchema": [
271
+ {"AttributeName": "agent_id", "KeyType": "HASH"},
272
+ {"AttributeName": "created_at", "KeyType": "RANGE"},
273
+ ],
274
+ "Projection": {"ProjectionType": "ALL"},
275
+ "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
276
+ },
277
+ {
278
+ "IndexName": "team_id-created_at-index",
279
+ "KeySchema": [
280
+ {"AttributeName": "team_id", "KeyType": "HASH"},
281
+ {"AttributeName": "created_at", "KeyType": "RANGE"},
282
+ ],
283
+ "Projection": {"ProjectionType": "ALL"},
284
+ "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
285
+ },
286
+ ],
287
+ "BillingMode": "PROVISIONED",
288
+ "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
289
+ }
290
+
255
291
 
256
292
  def get_table_schema_definition(table_type: str) -> Dict[str, Any]:
257
293
  """
@@ -269,6 +305,7 @@ def get_table_schema_definition(table_type: str) -> Dict[str, Any]:
269
305
  "evals": EVAL_TABLE_SCHEMA,
270
306
  "knowledge": KNOWLEDGE_TABLE_SCHEMA,
271
307
  "metrics": METRICS_TABLE_SCHEMA,
308
+ "culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
272
309
  }
273
310
 
274
311
  schema = schemas.get(table_type, {})
agno/db/dynamo/utils.py CHANGED
@@ -5,6 +5,7 @@ from typing import Any, Callable, Dict, List, Optional, Union
5
5
  from uuid import uuid4
6
6
 
7
7
  from agno.db.base import SessionType
8
+ from agno.db.schemas.culture import CulturalKnowledge
8
9
  from agno.db.schemas.evals import EvalRunRecord
9
10
  from agno.db.schemas.knowledge import KnowledgeRow
10
11
  from agno.session import Session
@@ -23,7 +24,7 @@ def serialize_to_dynamo_item(data: Dict[str, Any]) -> Dict[str, Any]:
23
24
  A DynamoDB-ready dict with the serialized data
24
25
 
25
26
  """
26
- item = {}
27
+ item: Dict[str, Any] = {}
27
28
  for key, value in data.items():
28
29
  if value is not None:
29
30
  if isinstance(value, (int, float)):
@@ -31,7 +32,7 @@ def serialize_to_dynamo_item(data: Dict[str, Any]) -> Dict[str, Any]:
31
32
  elif isinstance(value, str):
32
33
  item[key] = {"S": value}
33
34
  elif isinstance(value, bool):
34
- item[key] = {"BOOL": str(value)}
35
+ item[key] = {"BOOL": value}
35
36
  elif isinstance(value, (dict, list)):
36
37
  item[key] = {"S": json.dumps(value)}
37
38
  else:
@@ -342,7 +343,7 @@ def calculate_date_metrics(date_to_process: date, sessions_data: dict) -> dict:
342
343
  ]
343
344
  all_user_ids = set()
344
345
  for session_type, sessions_count_key, runs_count_key in session_types:
345
- sessions = sessions_data.get(session_type, [])
346
+ sessions = sessions_data.get(session_type, []) or []
346
347
  metrics[sessions_count_key] = len(sessions)
347
348
  for session in sessions:
348
349
  if session.get("user_id"):
@@ -360,7 +361,7 @@ def calculate_date_metrics(date_to_process: date, sessions_data: dict) -> dict:
360
361
  token_metrics[field] += session_metrics.get(field, 0)
361
362
  model_metrics = []
362
363
  for model, count in model_counts.items():
363
- model_id, model_provider = model.split(":")
364
+ model_id, model_provider = model.rsplit(":", 1)
364
365
  model_metrics.append({"model_id": model_id, "model_provider": model_provider, "count": count})
365
366
  metrics["users_count"] = len(all_user_ids)
366
367
  current_time = int(time.time())
@@ -682,3 +683,61 @@ def process_query_results(
682
683
  log_error(f"Failed to deserialize item: {e}")
683
684
 
684
685
  return deserialized_items
686
+
687
+
688
+ # -- Cultural Knowledge util methods --
689
+ def serialize_cultural_knowledge_for_db(cultural_knowledge: CulturalKnowledge) -> Dict[str, Any]:
690
+ """Serialize a CulturalKnowledge object for database storage.
691
+
692
+ Converts the model's separate content, categories, and notes fields
693
+ into a single JSON dict for the database content column.
694
+ DynamoDB supports nested maps/dicts natively.
695
+
696
+ Args:
697
+ cultural_knowledge (CulturalKnowledge): The cultural knowledge object to serialize.
698
+
699
+ Returns:
700
+ Dict[str, Any]: A dictionary with the content field as a dict containing content, categories, and notes.
701
+ """
702
+ content_dict: Dict[str, Any] = {}
703
+ if cultural_knowledge.content is not None:
704
+ content_dict["content"] = cultural_knowledge.content
705
+ if cultural_knowledge.categories is not None:
706
+ content_dict["categories"] = cultural_knowledge.categories
707
+ if cultural_knowledge.notes is not None:
708
+ content_dict["notes"] = cultural_knowledge.notes
709
+
710
+ return content_dict if content_dict else {}
711
+
712
+
713
+ def deserialize_cultural_knowledge_from_db(db_row: Dict[str, Any]) -> CulturalKnowledge:
714
+ """Deserialize a database row to a CulturalKnowledge object.
715
+
716
+ The database stores content as a dict containing content, categories, and notes.
717
+ This method extracts those fields and converts them back to the model format.
718
+
719
+ Args:
720
+ db_row (Dict[str, Any]): The database row as a dictionary.
721
+
722
+ Returns:
723
+ CulturalKnowledge: The cultural knowledge object.
724
+ """
725
+ # Extract content, categories, and notes from the content field
726
+ content_json = db_row.get("content", {}) or {}
727
+
728
+ return CulturalKnowledge.from_dict(
729
+ {
730
+ "id": db_row.get("id"),
731
+ "name": db_row.get("name"),
732
+ "summary": db_row.get("summary"),
733
+ "content": content_json.get("content"),
734
+ "categories": content_json.get("categories"),
735
+ "notes": content_json.get("notes"),
736
+ "metadata": db_row.get("metadata"),
737
+ "input": db_row.get("input"),
738
+ "created_at": db_row.get("created_at"),
739
+ "updated_at": db_row.get("updated_at"),
740
+ "agent_id": db_row.get("agent_id"),
741
+ "team_id": db_row.get("team_id"),
742
+ }
743
+ )