agno 2.2.1__py3-none-any.whl → 2.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. agno/agent/agent.py +735 -574
  2. agno/culture/manager.py +22 -24
  3. agno/db/async_postgres/__init__.py +1 -1
  4. agno/db/dynamo/dynamo.py +0 -2
  5. agno/db/firestore/firestore.py +0 -2
  6. agno/db/gcs_json/gcs_json_db.py +0 -4
  7. agno/db/gcs_json/utils.py +0 -24
  8. agno/db/in_memory/in_memory_db.py +0 -3
  9. agno/db/json/json_db.py +4 -10
  10. agno/db/json/utils.py +0 -24
  11. agno/db/mongo/__init__.py +15 -1
  12. agno/db/mongo/async_mongo.py +1999 -0
  13. agno/db/mongo/mongo.py +0 -2
  14. agno/db/mysql/mysql.py +0 -3
  15. agno/db/postgres/__init__.py +1 -1
  16. agno/db/{async_postgres → postgres}/async_postgres.py +19 -22
  17. agno/db/postgres/postgres.py +7 -10
  18. agno/db/postgres/utils.py +106 -2
  19. agno/db/redis/redis.py +0 -2
  20. agno/db/singlestore/singlestore.py +0 -3
  21. agno/db/sqlite/__init__.py +2 -1
  22. agno/db/sqlite/async_sqlite.py +2269 -0
  23. agno/db/sqlite/sqlite.py +0 -2
  24. agno/db/sqlite/utils.py +96 -0
  25. agno/db/surrealdb/surrealdb.py +0 -6
  26. agno/knowledge/knowledge.py +3 -3
  27. agno/knowledge/reader/reader_factory.py +16 -0
  28. agno/knowledge/reader/tavily_reader.py +194 -0
  29. agno/memory/manager.py +28 -25
  30. agno/models/anthropic/claude.py +63 -6
  31. agno/models/base.py +251 -32
  32. agno/models/response.py +69 -0
  33. agno/os/router.py +7 -5
  34. agno/os/routers/memory/memory.py +2 -1
  35. agno/os/routers/memory/schemas.py +5 -2
  36. agno/os/schema.py +25 -20
  37. agno/os/utils.py +9 -2
  38. agno/run/agent.py +23 -30
  39. agno/run/base.py +17 -1
  40. agno/run/team.py +23 -29
  41. agno/run/workflow.py +17 -12
  42. agno/session/agent.py +3 -0
  43. agno/session/summary.py +4 -1
  44. agno/session/team.py +1 -1
  45. agno/team/team.py +599 -367
  46. agno/tools/dalle.py +2 -4
  47. agno/tools/eleven_labs.py +23 -25
  48. agno/tools/function.py +40 -0
  49. agno/tools/mcp/__init__.py +10 -0
  50. agno/tools/mcp/mcp.py +324 -0
  51. agno/tools/mcp/multi_mcp.py +347 -0
  52. agno/tools/mcp/params.py +24 -0
  53. agno/tools/slack.py +18 -3
  54. agno/tools/tavily.py +146 -0
  55. agno/utils/agent.py +366 -1
  56. agno/utils/mcp.py +92 -2
  57. agno/utils/media.py +166 -1
  58. agno/utils/print_response/workflow.py +17 -1
  59. agno/utils/team.py +89 -1
  60. agno/workflow/step.py +0 -1
  61. agno/workflow/types.py +10 -15
  62. {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/METADATA +28 -25
  63. {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/RECORD +66 -62
  64. agno/db/async_postgres/schemas.py +0 -139
  65. agno/db/async_postgres/utils.py +0 -347
  66. agno/tools/mcp.py +0 -679
  67. {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/WHEEL +0 -0
  68. {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/licenses/LICENSE +0 -0
  69. {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/top_level.txt +0 -0
agno/culture/manager.py CHANGED
@@ -78,8 +78,6 @@ class CultureManager:
78
78
  self.delete_knowledge = delete_knowledge
79
79
  self.clear_knowledge = clear_knowledge
80
80
  self.debug_mode = debug_mode
81
- self._tools_for_model: Optional[List[Dict[str, Any]]] = None
82
- self._functions_for_model: Optional[Dict[str, Function]] = None
83
81
 
84
82
  def get_model(self) -> Model:
85
83
  if self.model is None:
@@ -316,23 +314,27 @@ class CultureManager:
316
314
  return response
317
315
 
318
316
  # -*- Utility Functions -*-
319
- def _determine_tools_for_model(self, tools: List[Callable]) -> None:
317
+ def _determine_tools_for_model(self, tools: List[Callable]) -> List[Union[Function, dict]]:
320
318
  # Have to reset each time, because of different user IDs
321
- self._tools_for_model = []
322
- self._functions_for_model = {}
319
+
320
+ _function_names = []
321
+ _functions: List[Union[Function, dict]] = []
323
322
 
324
323
  for tool in tools:
325
324
  try:
326
325
  function_name = tool.__name__
327
- if function_name not in self._functions_for_model:
328
- func = Function.from_callable(tool, strict=True) # type: ignore
329
- func.strict = True
330
- self._functions_for_model[func.name] = func
331
- self._tools_for_model.append({"type": "function", "function": func.to_dict()})
332
- log_debug(f"Added function {func.name}")
326
+ if function_name in _function_names:
327
+ continue
328
+ _function_names.append(function_name)
329
+ func = Function.from_callable(tool, strict=True) # type: ignore
330
+ func.strict = True
331
+ _functions.append(func)
332
+ log_debug(f"Added function {func.name}")
333
333
  except Exception as e:
334
334
  log_warning(f"Could not add function {tool}: {e}")
335
335
 
336
+ return _functions
337
+
336
338
  def get_system_message(
337
339
  self,
338
340
  existing_knowledge: Optional[List[Dict[str, Any]]] = None,
@@ -460,7 +462,7 @@ class CultureManager:
460
462
 
461
463
  model_copy = deepcopy(self.model)
462
464
  # Update the Model (set defaults, add logit etc.)
463
- self._determine_tools_for_model(
465
+ _tools = self._determine_tools_for_model(
464
466
  self._get_db_tools(
465
467
  db,
466
468
  enable_add_knowledge=add_knowledge,
@@ -485,8 +487,7 @@ class CultureManager:
485
487
  # Generate a response from the Model (includes running function calls)
486
488
  response = model_copy.response(
487
489
  messages=messages_for_model,
488
- tools=self._tools_for_model,
489
- functions=self._functions_for_model,
490
+ tools=_tools,
490
491
  )
491
492
 
492
493
  if response.tool_calls is not None and len(response.tool_calls) > 0:
@@ -513,7 +514,7 @@ class CultureManager:
513
514
  model_copy = deepcopy(self.model)
514
515
  db = cast(AsyncBaseDb, db)
515
516
 
516
- self._determine_tools_for_model(
517
+ _tools = self._determine_tools_for_model(
517
518
  await self._aget_db_tools(
518
519
  db,
519
520
  enable_update_knowledge=update_knowledge,
@@ -535,8 +536,7 @@ class CultureManager:
535
536
  # Generate a response from the Model (includes running function calls)
536
537
  response = await model_copy.aresponse(
537
538
  messages=messages_for_model,
538
- tools=self._tools_for_model,
539
- functions=self._functions_for_model,
539
+ tools=_tools,
540
540
  )
541
541
 
542
542
  if response.tool_calls is not None and len(response.tool_calls) > 0:
@@ -564,7 +564,7 @@ class CultureManager:
564
564
 
565
565
  model_copy = deepcopy(self.model)
566
566
  # Update the Model (set defaults, add logit etc.)
567
- self._determine_tools_for_model(
567
+ _tools = self._determine_tools_for_model(
568
568
  self._get_db_tools(
569
569
  db,
570
570
  enable_delete_knowledge=delete_knowledge,
@@ -590,8 +590,7 @@ class CultureManager:
590
590
  # Generate a response from the Model (includes running function calls)
591
591
  response = model_copy.response(
592
592
  messages=messages_for_model,
593
- tools=self._tools_for_model,
594
- functions=self._functions_for_model,
593
+ tools=_tools,
595
594
  )
596
595
 
597
596
  if response.tool_calls is not None and len(response.tool_calls) > 0:
@@ -620,7 +619,7 @@ class CultureManager:
620
619
  model_copy = deepcopy(self.model)
621
620
  # Update the Model (set defaults, add logit etc.)
622
621
  if isinstance(db, AsyncBaseDb):
623
- self._determine_tools_for_model(
622
+ _tools = self._determine_tools_for_model(
624
623
  await self._aget_db_tools(
625
624
  db,
626
625
  enable_delete_knowledge=delete_knowledge,
@@ -630,7 +629,7 @@ class CultureManager:
630
629
  ),
631
630
  )
632
631
  else:
633
- self._determine_tools_for_model(
632
+ _tools = self._determine_tools_for_model(
634
633
  self._get_db_tools(
635
634
  db,
636
635
  enable_delete_knowledge=delete_knowledge,
@@ -656,8 +655,7 @@ class CultureManager:
656
655
  # Generate a response from the Model (includes running function calls)
657
656
  response = await model_copy.aresponse(
658
657
  messages=messages_for_model,
659
- tools=self._tools_for_model,
660
- functions=self._functions_for_model,
658
+ tools=_tools,
661
659
  )
662
660
 
663
661
  if response.tool_calls is not None and len(response.tool_calls) > 0:
@@ -1,3 +1,3 @@
1
- from agno.db.async_postgres.async_postgres import AsyncPostgresDb
1
+ from agno.db.postgres import AsyncPostgresDb
2
2
 
3
3
  __all__ = ["AsyncPostgresDb"]
agno/db/dynamo/dynamo.py CHANGED
@@ -277,8 +277,6 @@ class DynamoDb(BaseDb):
277
277
 
278
278
  session = deserialize_from_dynamodb_item(item)
279
279
 
280
- if session.get("session_type") != session_type.value:
281
- return None
282
280
  if user_id and session.get("user_id") != user_id:
283
281
  return None
284
282
 
@@ -280,8 +280,6 @@ class FirestoreDb(BaseDb):
280
280
 
281
281
  if user_id is not None:
282
282
  query = query.where(filter=FieldFilter("user_id", "==", user_id))
283
- if session_type is not None:
284
- query = query.where(filter=FieldFilter("session_type", "==", session_type.value))
285
283
 
286
284
  docs = query.stream()
287
285
  result = None
@@ -220,10 +220,6 @@ class GcsJsonDb(BaseDb):
220
220
  if user_id is not None and session_data.get("user_id") != user_id:
221
221
  continue
222
222
 
223
- session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
224
- if session_data.get("session_type") != session_type_value:
225
- continue
226
-
227
223
  if not deserialize:
228
224
  return session_data
229
225
 
agno/db/gcs_json/utils.py CHANGED
@@ -5,34 +5,10 @@ from datetime import date, datetime, timedelta, timezone
5
5
  from typing import Any, Dict, List, Optional
6
6
  from uuid import uuid4
7
7
 
8
- from agno.db.base import SessionType
9
8
  from agno.db.schemas.culture import CulturalKnowledge
10
- from agno.run.agent import RunOutput
11
- from agno.run.team import TeamRunOutput
12
- from agno.session.summary import SessionSummary
13
9
  from agno.utils.log import log_debug
14
10
 
15
11
 
16
- def hydrate_session(session: dict) -> dict:
17
- """Convert nested dictionaries to their corresponding object types.
18
-
19
- Args:
20
- session (dict): The session dictionary to hydrate.
21
-
22
- Returns:
23
- dict: The hydrated session dictionary.
24
- """
25
- if session.get("summary") is not None:
26
- session["summary"] = SessionSummary.from_dict(session["summary"])
27
- if session.get("runs") is not None:
28
- if session["session_type"] == SessionType.AGENT:
29
- session["runs"] = [RunOutput.from_dict(run) for run in session["runs"]]
30
- elif session["session_type"] == SessionType.TEAM:
31
- session["runs"] = [TeamRunOutput.from_dict(run) for run in session["runs"]]
32
-
33
- return session
34
-
35
-
36
12
  def apply_sorting(
37
13
  data: List[Dict[str, Any]], sort_by: Optional[str] = None, sort_order: Optional[str] = None
38
14
  ) -> List[Dict[str, Any]]:
@@ -108,9 +108,6 @@ class InMemoryDb(BaseDb):
108
108
  if session_data.get("session_id") == session_id:
109
109
  if user_id is not None and session_data.get("user_id") != user_id:
110
110
  continue
111
- session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
112
- if session_data.get("session_type") != session_type_value:
113
- continue
114
111
 
115
112
  session_data_copy = deepcopy(session_data)
116
113
 
agno/db/json/json_db.py CHANGED
@@ -13,7 +13,6 @@ from agno.db.json.utils import (
13
13
  deserialize_cultural_knowledge_from_db,
14
14
  fetch_all_sessions_data,
15
15
  get_dates_to_calculate_metrics_for,
16
- hydrate_session,
17
16
  serialize_cultural_knowledge_for_db,
18
17
  )
19
18
  from agno.db.schemas.culture import CulturalKnowledge
@@ -202,21 +201,16 @@ class JsonDb(BaseDb):
202
201
  if session_data.get("session_id") == session_id:
203
202
  if user_id is not None and session_data.get("user_id") != user_id:
204
203
  continue
205
- session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
206
- if session_data.get("session_type") != session_type_value:
207
- continue
208
-
209
- session = hydrate_session(session_data)
210
204
 
211
205
  if not deserialize:
212
- return session
206
+ return session_data
213
207
 
214
208
  if session_type == SessionType.AGENT:
215
- return AgentSession.from_dict(session)
209
+ return AgentSession.from_dict(session_data)
216
210
  elif session_type == SessionType.TEAM:
217
- return TeamSession.from_dict(session)
211
+ return TeamSession.from_dict(session_data)
218
212
  elif session_type == SessionType.WORKFLOW:
219
- return WorkflowSession.from_dict(session)
213
+ return WorkflowSession.from_dict(session_data)
220
214
  else:
221
215
  raise ValueError(f"Invalid session type: {session_type}")
222
216
 
agno/db/json/utils.py CHANGED
@@ -5,34 +5,10 @@ from datetime import date, datetime, timedelta, timezone
5
5
  from typing import Any, Dict, List, Optional
6
6
  from uuid import uuid4
7
7
 
8
- from agno.db.base import SessionType
9
8
  from agno.db.schemas.culture import CulturalKnowledge
10
- from agno.run.agent import RunOutput
11
- from agno.run.team import TeamRunOutput
12
- from agno.session.summary import SessionSummary
13
9
  from agno.utils.log import log_debug
14
10
 
15
11
 
16
- def hydrate_session(session: dict) -> dict:
17
- """Convert nested dictionaries to their corresponding object types.
18
-
19
- Args:
20
- session (dict): The session dictionary to hydrate.
21
-
22
- Returns:
23
- dict: The hydrated session dictionary.
24
- """
25
- if session.get("summary") is not None:
26
- session["summary"] = SessionSummary.from_dict(session["summary"])
27
- if session.get("runs") is not None:
28
- if session["session_type"] == SessionType.AGENT:
29
- session["runs"] = [RunOutput.from_dict(run) for run in session["runs"]]
30
- elif session["session_type"] == SessionType.TEAM:
31
- session["runs"] = [TeamRunOutput.from_dict(run) for run in session["runs"]]
32
-
33
- return session
34
-
35
-
36
12
  def apply_sorting(
37
13
  data: List[Dict[str, Any]], sort_by: Optional[str] = None, sort_order: Optional[str] = None
38
14
  ) -> List[Dict[str, Any]]:
agno/db/mongo/__init__.py CHANGED
@@ -1,3 +1,17 @@
1
+ from typing import TYPE_CHECKING
2
+
1
3
  from agno.db.mongo.mongo import MongoDb
2
4
 
3
- __all__ = ["MongoDb"]
5
+ if TYPE_CHECKING:
6
+ from agno.db.mongo.async_mongo import AsyncMongoDb
7
+
8
+ __all__ = ["AsyncMongoDb", "MongoDb"]
9
+
10
+
11
+ def __getattr__(name: str):
12
+ """Lazy import AsyncMongoDb only when accessed."""
13
+ if name == "AsyncMongoDb":
14
+ from agno.db.mongo.async_mongo import AsyncMongoDb
15
+
16
+ return AsyncMongoDb
17
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")