agno 2.0.8__py3-none-any.whl → 2.0.9__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 (45) hide show
  1. agno/agent/agent.py +2 -2
  2. agno/db/base.py +14 -0
  3. agno/db/dynamo/dynamo.py +107 -27
  4. agno/db/firestore/firestore.py +109 -33
  5. agno/db/gcs_json/gcs_json_db.py +100 -20
  6. agno/db/in_memory/in_memory_db.py +95 -20
  7. agno/db/json/json_db.py +101 -21
  8. agno/db/migrations/v1_to_v2.py +181 -35
  9. agno/db/mongo/mongo.py +251 -26
  10. agno/db/mysql/mysql.py +307 -6
  11. agno/db/postgres/postgres.py +279 -33
  12. agno/db/redis/redis.py +99 -22
  13. agno/db/singlestore/singlestore.py +319 -38
  14. agno/db/sqlite/sqlite.py +339 -23
  15. agno/models/anthropic/claude.py +0 -20
  16. agno/models/huggingface/huggingface.py +2 -1
  17. agno/models/ollama/chat.py +28 -2
  18. agno/models/openai/chat.py +7 -0
  19. agno/models/openai/responses.py +8 -8
  20. agno/os/interfaces/base.py +2 -0
  21. agno/os/interfaces/slack/router.py +50 -10
  22. agno/os/interfaces/slack/slack.py +6 -4
  23. agno/os/interfaces/whatsapp/router.py +7 -4
  24. agno/os/router.py +18 -0
  25. agno/os/utils.py +2 -2
  26. agno/reasoning/azure_ai_foundry.py +2 -2
  27. agno/reasoning/deepseek.py +2 -2
  28. agno/reasoning/groq.py +2 -2
  29. agno/reasoning/ollama.py +2 -2
  30. agno/reasoning/openai.py +2 -2
  31. agno/run/base.py +15 -2
  32. agno/team/team.py +0 -7
  33. agno/tools/mcp_toolbox.py +284 -0
  34. agno/tools/scrapegraph.py +58 -31
  35. agno/tools/whatsapp.py +1 -1
  36. agno/utils/print_response/agent.py +2 -2
  37. agno/utils/print_response/team.py +6 -6
  38. agno/utils/reasoning.py +22 -1
  39. agno/utils/string.py +9 -0
  40. agno/workflow/workflow.py +0 -1
  41. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/METADATA +4 -1
  42. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/RECORD +45 -44
  43. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/WHEEL +0 -0
  44. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/licenses/LICENSE +0 -0
  45. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/top_level.txt +0 -0
agno/agent/agent.py CHANGED
@@ -7406,8 +7406,8 @@ class Agent:
7406
7406
  "parser_model": self.parser_model.to_dict() if self.parser_model else None,
7407
7407
  "output_model": self.output_model.to_dict() if self.output_model else None,
7408
7408
  "has_tools": self.tools is not None,
7409
- "has_memory": self.enable_user_memories is not None,
7410
- "has_reasoning": self.reasoning is not None,
7409
+ "has_memory": self.enable_user_memories is True,
7410
+ "has_reasoning": self.reasoning is True,
7411
7411
  "has_knowledge": self.knowledge is not None,
7412
7412
  "has_input_schema": self.input_schema is not None,
7413
7413
  "has_output_schema": self.output_schema is not None,
agno/db/base.py CHANGED
@@ -81,6 +81,13 @@ class BaseDb(ABC):
81
81
  ) -> Optional[Union[Session, Dict[str, Any]]]:
82
82
  raise NotImplementedError
83
83
 
84
+ @abstractmethod
85
+ def upsert_sessions(
86
+ self, sessions: List[Session], deserialize: Optional[bool] = True
87
+ ) -> List[Union[Session, Dict[str, Any]]]:
88
+ """Bulk upsert multiple sessions for improved performance on large datasets."""
89
+ raise NotImplementedError
90
+
84
91
  # --- Memory ---
85
92
 
86
93
  @abstractmethod
@@ -135,6 +142,13 @@ class BaseDb(ABC):
135
142
  ) -> Optional[Union[UserMemory, Dict[str, Any]]]:
136
143
  raise NotImplementedError
137
144
 
145
+ @abstractmethod
146
+ def upsert_memories(
147
+ self, memories: List[UserMemory], deserialize: Optional[bool] = True
148
+ ) -> List[Union[UserMemory, Dict[str, Any]]]:
149
+ """Bulk upsert multiple memories for improved performance on large datasets."""
150
+ raise NotImplementedError
151
+
138
152
  # --- Metrics ---
139
153
  @abstractmethod
140
154
  def get_metrics(
agno/db/dynamo/dynamo.py CHANGED
@@ -31,7 +31,7 @@ from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
31
31
  from agno.db.schemas.knowledge import KnowledgeRow
32
32
  from agno.db.schemas.memory import UserMemory
33
33
  from agno.session import AgentSession, Session, TeamSession, WorkflowSession
34
- from agno.utils.log import log_debug, log_error
34
+ from agno.utils.log import log_debug, log_error, log_info
35
35
  from agno.utils.string import generate_id
36
36
 
37
37
  try:
@@ -232,6 +232,7 @@ class DynamoDb(BaseDb):
232
232
 
233
233
  except Exception as e:
234
234
  log_error(f"Failed to delete sessions: {e}")
235
+ raise e
235
236
 
236
237
  def get_session(
237
238
  self,
@@ -290,7 +291,7 @@ class DynamoDb(BaseDb):
290
291
 
291
292
  except Exception as e:
292
293
  log_error(f"Failed to get session {session_id}: {e}")
293
- return None
294
+ raise e
294
295
 
295
296
  def get_sessions(
296
297
  self,
@@ -410,7 +411,7 @@ class DynamoDb(BaseDb):
410
411
 
411
412
  except Exception as e:
412
413
  log_error(f"Failed to get sessions: {e}")
413
- return []
414
+ raise e
414
415
 
415
416
  def rename_session(
416
417
  self,
@@ -478,7 +479,7 @@ class DynamoDb(BaseDb):
478
479
 
479
480
  except Exception as e:
480
481
  log_error(f"Failed to rename session {session_id}: {e}")
481
- return None
482
+ raise e
482
483
 
483
484
  def upsert_session(
484
485
  self, session: Session, deserialize: Optional[bool] = True
@@ -520,7 +521,44 @@ class DynamoDb(BaseDb):
520
521
 
521
522
  except Exception as e:
522
523
  log_error(f"Failed to upsert session {session.session_id}: {e}")
523
- return None
524
+ raise e
525
+
526
+ def upsert_sessions(
527
+ self, sessions: List[Session], deserialize: Optional[bool] = True
528
+ ) -> List[Union[Session, Dict[str, Any]]]:
529
+ """
530
+ Bulk upsert multiple sessions for improved performance on large datasets.
531
+
532
+ Args:
533
+ sessions (List[Session]): List of sessions to upsert.
534
+ deserialize (Optional[bool]): Whether to deserialize the sessions. Defaults to True.
535
+
536
+ Returns:
537
+ List[Union[Session, Dict[str, Any]]]: List of upserted sessions.
538
+
539
+ Raises:
540
+ Exception: If an error occurs during bulk upsert.
541
+ """
542
+ if not sessions:
543
+ return []
544
+
545
+ try:
546
+ log_info(
547
+ f"DynamoDb doesn't support efficient bulk operations, falling back to individual upserts for {len(sessions)} sessions"
548
+ )
549
+
550
+ # Fall back to individual upserts
551
+ results = []
552
+ for session in sessions:
553
+ if session is not None:
554
+ result = self.upsert_session(session, deserialize=deserialize)
555
+ if result is not None:
556
+ results.append(result)
557
+ return results
558
+
559
+ except Exception as e:
560
+ log_error(f"Exception during bulk session upsert: {e}")
561
+ return []
524
562
 
525
563
  # --- User Memory ---
526
564
 
@@ -543,6 +581,7 @@ class DynamoDb(BaseDb):
543
581
 
544
582
  except Exception as e:
545
583
  log_error(f"Failed to delete user memory {memory_id}: {e}")
584
+ raise e
546
585
 
547
586
  def delete_user_memories(self, memory_ids: List[str]) -> None:
548
587
  """
@@ -567,6 +606,7 @@ class DynamoDb(BaseDb):
567
606
 
568
607
  except Exception as e:
569
608
  log_error(f"Failed to delete user memories: {e}")
609
+ raise e
570
610
 
571
611
  def get_all_memory_topics(self) -> List[str]:
572
612
  """Get all memory topics from the database.
@@ -599,7 +639,7 @@ class DynamoDb(BaseDb):
599
639
 
600
640
  except Exception as e:
601
641
  log_error(f"Exception reading from memory table: {e}")
602
- return []
642
+ raise e
603
643
 
604
644
  def get_user_memory(
605
645
  self, memory_id: str, deserialize: Optional[bool] = True
@@ -632,7 +672,7 @@ class DynamoDb(BaseDb):
632
672
 
633
673
  except Exception as e:
634
674
  log_error(f"Failed to get user memory {memory_id}: {e}")
635
- return None
675
+ raise e
636
676
 
637
677
  def get_user_memories(
638
678
  self,
@@ -752,7 +792,7 @@ class DynamoDb(BaseDb):
752
792
 
753
793
  except Exception as e:
754
794
  log_error(f"Failed to get user memories: {e}")
755
- return [] if deserialize else ([], 0)
795
+ raise e
756
796
 
757
797
  def get_user_memory_stats(
758
798
  self,
@@ -838,7 +878,7 @@ class DynamoDb(BaseDb):
838
878
 
839
879
  except Exception as e:
840
880
  log_error(f"Failed to get user memory stats: {e}")
841
- return [], 0
881
+ raise e
842
882
 
843
883
  def upsert_user_memory(
844
884
  self, memory: UserMemory, deserialize: Optional[bool] = True
@@ -867,7 +907,44 @@ class DynamoDb(BaseDb):
867
907
 
868
908
  except Exception as e:
869
909
  log_error(f"Failed to upsert user memory: {e}")
870
- return None
910
+ raise e
911
+
912
+ def upsert_memories(
913
+ self, memories: List[UserMemory], deserialize: Optional[bool] = True
914
+ ) -> List[Union[UserMemory, Dict[str, Any]]]:
915
+ """
916
+ Bulk upsert multiple user memories for improved performance on large datasets.
917
+
918
+ Args:
919
+ memories (List[UserMemory]): List of memories to upsert.
920
+ deserialize (Optional[bool]): Whether to deserialize the memories. Defaults to True.
921
+
922
+ Returns:
923
+ List[Union[UserMemory, Dict[str, Any]]]: List of upserted memories.
924
+
925
+ Raises:
926
+ Exception: If an error occurs during bulk upsert.
927
+ """
928
+ if not memories:
929
+ return []
930
+
931
+ try:
932
+ log_info(
933
+ f"DynamoDb doesn't support efficient bulk operations, falling back to individual upserts for {len(memories)} memories"
934
+ )
935
+
936
+ # Fall back to individual upserts
937
+ results = []
938
+ for memory in memories:
939
+ if memory is not None:
940
+ result = self.upsert_user_memory(memory, deserialize=deserialize)
941
+ if result is not None:
942
+ results.append(result)
943
+ return results
944
+
945
+ except Exception as e:
946
+ log_error(f"Exception during bulk memory upsert: {e}")
947
+ return []
871
948
 
872
949
  def clear_memories(self) -> None:
873
950
  """Delete all memories from the database.
@@ -908,6 +985,7 @@ class DynamoDb(BaseDb):
908
985
  from agno.utils.log import log_warning
909
986
 
910
987
  log_warning(f"Exception deleting all memories: {e}")
988
+ raise e
911
989
 
912
990
  # --- Metrics ---
913
991
 
@@ -985,7 +1063,7 @@ class DynamoDb(BaseDb):
985
1063
 
986
1064
  except Exception as e:
987
1065
  log_error(f"Failed to calculate metrics: {e}")
988
- return None
1066
+ raise e
989
1067
 
990
1068
  def _get_metrics_calculation_starting_date(self) -> Optional[date]:
991
1069
  """Get the first date for which metrics calculation is needed:
@@ -1071,7 +1149,7 @@ class DynamoDb(BaseDb):
1071
1149
 
1072
1150
  except Exception as e:
1073
1151
  log_error(f"Failed to get metrics calculation starting date: {e}")
1074
- return None
1152
+ raise e
1075
1153
 
1076
1154
  def _get_all_sessions_for_metrics_calculation(
1077
1155
  self, start_timestamp: int, end_timestamp: int
@@ -1129,7 +1207,7 @@ class DynamoDb(BaseDb):
1129
1207
 
1130
1208
  except Exception as e:
1131
1209
  log_error(f"Failed to get sessions for metrics calculation: {e}")
1132
- return []
1210
+ raise e
1133
1211
 
1134
1212
  def _bulk_upsert_metrics(self, metrics_records: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
1135
1213
  """Bulk upsert metrics records into DynamoDB with proper deduplication.
@@ -1157,7 +1235,7 @@ class DynamoDb(BaseDb):
1157
1235
 
1158
1236
  except Exception as e:
1159
1237
  log_error(f"Failed to bulk upsert metrics: {e}")
1160
- return []
1238
+ raise e
1161
1239
 
1162
1240
  def _upsert_single_metrics_record(self, table_name: str, record: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1163
1241
  """Upsert a single metrics record, checking for existing records with the same date.
@@ -1189,7 +1267,7 @@ class DynamoDb(BaseDb):
1189
1267
 
1190
1268
  except Exception as e:
1191
1269
  log_error(f"Failed to upsert single metrics record: {e}")
1192
- return None
1270
+ raise e
1193
1271
 
1194
1272
  def _get_existing_metrics_record(self, table_name: str, date_str: str) -> Optional[Dict[str, Any]]:
1195
1273
  """Get existing metrics record for a given date.
@@ -1222,7 +1300,7 @@ class DynamoDb(BaseDb):
1222
1300
 
1223
1301
  except Exception as e:
1224
1302
  log_error(f"Failed to get existing metrics record for date {date_str}: {e}")
1225
- return None
1303
+ raise e
1226
1304
 
1227
1305
  def _update_existing_metrics_record(
1228
1306
  self,
@@ -1256,7 +1334,7 @@ class DynamoDb(BaseDb):
1256
1334
 
1257
1335
  except Exception as e:
1258
1336
  log_error(f"Failed to update existing metrics record: {e}")
1259
- return None
1337
+ raise e
1260
1338
 
1261
1339
  def _create_new_metrics_record(self, table_name: str, record: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1262
1340
  """Create a new metrics record.
@@ -1280,7 +1358,7 @@ class DynamoDb(BaseDb):
1280
1358
 
1281
1359
  except Exception as e:
1282
1360
  log_error(f"Failed to create new metrics record: {e}")
1283
- return None
1361
+ raise e
1284
1362
 
1285
1363
  def _prepare_metrics_record_for_dynamo(self, record: Dict[str, Any]) -> Dict[str, Any]:
1286
1364
  """Prepare a metrics record for DynamoDB serialization by converting all data types properly.
@@ -1403,7 +1481,7 @@ class DynamoDb(BaseDb):
1403
1481
 
1404
1482
  except Exception as e:
1405
1483
  log_error(f"Failed to get metrics: {e}")
1406
- return [], 0
1484
+ raise e
1407
1485
 
1408
1486
  # --- Knowledge methods ---
1409
1487
 
@@ -1425,6 +1503,7 @@ class DynamoDb(BaseDb):
1425
1503
 
1426
1504
  except Exception as e:
1427
1505
  log_error(f"Failed to delete knowledge content {id}: {e}")
1506
+ raise e
1428
1507
 
1429
1508
  def get_knowledge_content(self, id: str) -> Optional[KnowledgeRow]:
1430
1509
  """Get a knowledge row from the database.
@@ -1447,7 +1526,7 @@ class DynamoDb(BaseDb):
1447
1526
 
1448
1527
  except Exception as e:
1449
1528
  log_error(f"Failed to get knowledge content {id}: {e}")
1450
- return None
1529
+ raise e
1451
1530
 
1452
1531
  def get_knowledge_contents(
1453
1532
  self,
@@ -1519,7 +1598,7 @@ class DynamoDb(BaseDb):
1519
1598
 
1520
1599
  except Exception as e:
1521
1600
  log_error(f"Failed to get knowledge contents: {e}")
1522
- return [], 0
1601
+ raise e
1523
1602
 
1524
1603
  def upsert_knowledge_content(self, knowledge_row: KnowledgeRow):
1525
1604
  """Upsert knowledge content in the database.
@@ -1540,7 +1619,7 @@ class DynamoDb(BaseDb):
1540
1619
 
1541
1620
  except Exception as e:
1542
1621
  log_error(f"Failed to upsert knowledge content {knowledge_row.id}: {e}")
1543
- return None
1622
+ raise e
1544
1623
 
1545
1624
  # --- Eval ---
1546
1625
 
@@ -1570,7 +1649,7 @@ class DynamoDb(BaseDb):
1570
1649
 
1571
1650
  except Exception as e:
1572
1651
  log_error(f"Failed to create eval run: {e}")
1573
- return None
1652
+ raise e
1574
1653
 
1575
1654
  def delete_eval_runs(self, eval_run_ids: List[str]) -> None:
1576
1655
  if not eval_run_ids or not self.eval_table_name:
@@ -1588,6 +1667,7 @@ class DynamoDb(BaseDb):
1588
1667
 
1589
1668
  except Exception as e:
1590
1669
  log_error(f"Failed to delete eval runs: {e}")
1670
+ raise e
1591
1671
 
1592
1672
  def get_eval_run_raw(self, eval_run_id: str, table: Optional[Any] = None) -> Optional[Dict[str, Any]]:
1593
1673
  if not self.eval_table_name:
@@ -1603,7 +1683,7 @@ class DynamoDb(BaseDb):
1603
1683
 
1604
1684
  except Exception as e:
1605
1685
  log_error(f"Failed to get eval run {eval_run_id}: {e}")
1606
- return None
1686
+ raise e
1607
1687
 
1608
1688
  def get_eval_run(self, eval_run_id: str, table: Optional[Any] = None) -> Optional[EvalRunRecord]:
1609
1689
  if not self.eval_table_name:
@@ -1619,7 +1699,7 @@ class DynamoDb(BaseDb):
1619
1699
 
1620
1700
  except Exception as e:
1621
1701
  log_error(f"Failed to get eval run {eval_run_id}: {e}")
1622
- return None
1702
+ raise e
1623
1703
 
1624
1704
  def get_eval_runs(
1625
1705
  self,
@@ -1718,7 +1798,7 @@ class DynamoDb(BaseDb):
1718
1798
 
1719
1799
  except Exception as e:
1720
1800
  log_error(f"Failed to get eval runs: {e}")
1721
- return [] if deserialize else ([], 0)
1801
+ raise e
1722
1802
 
1723
1803
  def rename_eval_run(
1724
1804
  self, eval_run_id: str, name: str, deserialize: Optional[bool] = True
@@ -1750,4 +1830,4 @@ class DynamoDb(BaseDb):
1750
1830
 
1751
1831
  except Exception as e:
1752
1832
  log_error(f"Failed to rename eval run {eval_run_id}: {e}")
1753
- return None
1833
+ raise e