agno 2.2.8__py3-none-any.whl → 2.2.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 (42) hide show
  1. agno/agent/agent.py +23 -15
  2. agno/db/base.py +23 -0
  3. agno/db/dynamo/dynamo.py +20 -25
  4. agno/db/dynamo/schemas.py +1 -0
  5. agno/db/firestore/firestore.py +11 -0
  6. agno/db/gcs_json/gcs_json_db.py +4 -0
  7. agno/db/in_memory/in_memory_db.py +4 -0
  8. agno/db/json/json_db.py +4 -0
  9. agno/db/mongo/async_mongo.py +27 -0
  10. agno/db/mongo/mongo.py +25 -0
  11. agno/db/mysql/mysql.py +26 -1
  12. agno/db/postgres/async_postgres.py +26 -1
  13. agno/db/postgres/postgres.py +26 -1
  14. agno/db/redis/redis.py +4 -0
  15. agno/db/singlestore/singlestore.py +24 -0
  16. agno/db/sqlite/async_sqlite.py +25 -1
  17. agno/db/sqlite/sqlite.py +25 -1
  18. agno/db/surrealdb/surrealdb.py +13 -1
  19. agno/knowledge/reader/docx_reader.py +0 -1
  20. agno/models/azure/ai_foundry.py +2 -1
  21. agno/models/cerebras/cerebras.py +3 -2
  22. agno/models/openai/chat.py +2 -1
  23. agno/models/openai/responses.py +2 -1
  24. agno/os/app.py +112 -50
  25. agno/os/config.py +1 -0
  26. agno/os/interfaces/agui/router.py +9 -0
  27. agno/os/interfaces/agui/utils.py +49 -3
  28. agno/os/mcp.py +8 -8
  29. agno/os/router.py +27 -9
  30. agno/os/routers/evals/evals.py +12 -7
  31. agno/os/routers/memory/memory.py +18 -10
  32. agno/os/routers/metrics/metrics.py +6 -4
  33. agno/os/routers/session/session.py +21 -11
  34. agno/os/utils.py +57 -11
  35. agno/team/team.py +26 -21
  36. agno/vectordb/mongodb/__init__.py +7 -1
  37. agno/vectordb/redis/__init__.py +4 -0
  38. {agno-2.2.8.dist-info → agno-2.2.9.dist-info}/METADATA +11 -13
  39. {agno-2.2.8.dist-info → agno-2.2.9.dist-info}/RECORD +42 -42
  40. {agno-2.2.8.dist-info → agno-2.2.9.dist-info}/WHEEL +0 -0
  41. {agno-2.2.8.dist-info → agno-2.2.9.dist-info}/licenses/LICENSE +0 -0
  42. {agno-2.2.8.dist-info → agno-2.2.9.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
34
34
 
35
35
 
36
36
  def get_eval_router(
37
- dbs: dict[str, Union[BaseDb, AsyncBaseDb]],
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(),
@@ -56,7 +56,7 @@ def get_eval_router(
56
56
 
57
57
  def attach_routes(
58
58
  router: APIRouter,
59
- dbs: dict[str, Union[BaseDb, AsyncBaseDb]],
59
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
60
60
  agents: Optional[List[Agent]] = None,
61
61
  teams: Optional[List[Team]] = None,
62
62
  ) -> APIRouter:
@@ -115,8 +115,9 @@ def attach_routes(
115
115
  sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
116
116
  sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
117
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"),
118
119
  ) -> PaginatedResponse[EvalSchema]:
119
- db = get_db(dbs, db_id)
120
+ db = await get_db(dbs, db_id, table)
120
121
 
121
122
  if isinstance(db, AsyncBaseDb):
122
123
  db = cast(AsyncBaseDb, db)
@@ -198,8 +199,9 @@ def attach_routes(
198
199
  async def get_eval_run(
199
200
  eval_run_id: str,
200
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"),
201
203
  ) -> EvalSchema:
202
- db = get_db(dbs, db_id)
204
+ db = await get_db(dbs, db_id, table)
203
205
  if isinstance(db, AsyncBaseDb):
204
206
  db = cast(AsyncBaseDb, db)
205
207
  eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
@@ -224,9 +226,10 @@ def attach_routes(
224
226
  async def delete_eval_runs(
225
227
  request: DeleteEvalRunsRequest,
226
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"),
227
230
  ) -> None:
228
231
  try:
229
- db = get_db(dbs, db_id)
232
+ db = await get_db(dbs, db_id, table)
230
233
  if isinstance(db, AsyncBaseDb):
231
234
  db = cast(AsyncBaseDb, db)
232
235
  await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
@@ -277,9 +280,10 @@ def attach_routes(
277
280
  eval_run_id: str,
278
281
  request: UpdateEvalRunRequest,
279
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"),
280
284
  ) -> EvalSchema:
281
285
  try:
282
- db = get_db(dbs, db_id)
286
+ db = await get_db(dbs, db_id, table)
283
287
  if isinstance(db, AsyncBaseDb):
284
288
  db = cast(AsyncBaseDb, db)
285
289
  eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
@@ -336,8 +340,9 @@ def attach_routes(
336
340
  async def run_eval(
337
341
  eval_run_input: EvalRunInput,
338
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"),
339
344
  ) -> Optional[EvalSchema]:
340
- db = get_db(dbs, db_id)
345
+ db = await get_db(dbs, db_id, table)
341
346
 
342
347
  if eval_run_input.agent_id and eval_run_input.team_id:
343
348
  raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
@@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
32
32
 
33
33
 
34
34
  def get_memory_router(
35
- dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
35
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
36
36
  ) -> APIRouter:
37
37
  """Create memory router with comprehensive OpenAPI documentation for user memory management endpoints."""
38
38
  router = APIRouter(
@@ -49,7 +49,7 @@ def get_memory_router(
49
49
  return attach_routes(router=router, dbs=dbs)
50
50
 
51
51
 
52
- def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
52
+ def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
53
53
  @router.post(
54
54
  "/memories",
55
55
  response_model=UserMemorySchema,
@@ -85,6 +85,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
85
85
  request: Request,
86
86
  payload: UserMemoryCreateSchema,
87
87
  db_id: Optional[str] = Query(default=None, description="Database ID to use for memory storage"),
88
+ table: Optional[str] = Query(default=None, description="Table to use for memory storage"),
88
89
  ) -> UserMemorySchema:
89
90
  if hasattr(request.state, "user_id"):
90
91
  user_id = request.state.user_id
@@ -93,7 +94,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
93
94
  if payload.user_id is None:
94
95
  raise HTTPException(status_code=400, detail="User ID is required")
95
96
 
96
- db = get_db(dbs, db_id)
97
+ db = await get_db(dbs, db_id, table)
97
98
 
98
99
  if isinstance(db, AsyncBaseDb):
99
100
  db = cast(AsyncBaseDb, db)
@@ -138,8 +139,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
138
139
  memory_id: str = Path(description="Memory ID to delete"),
139
140
  user_id: Optional[str] = Query(default=None, description="User ID to delete memory for"),
140
141
  db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
142
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
141
143
  ) -> None:
142
- db = get_db(dbs, db_id)
144
+ db = await get_db(dbs, db_id, table)
143
145
  if isinstance(db, AsyncBaseDb):
144
146
  db = cast(AsyncBaseDb, db)
145
147
  await db.delete_user_memory(memory_id=memory_id, user_id=user_id)
@@ -164,8 +166,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
164
166
  async def delete_memories(
165
167
  request: DeleteMemoriesRequest,
166
168
  db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
169
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
167
170
  ) -> None:
168
- db = get_db(dbs, db_id)
171
+ db = await get_db(dbs, db_id, table)
169
172
  if isinstance(db, AsyncBaseDb):
170
173
  db = cast(AsyncBaseDb, db)
171
174
  await db.delete_user_memories(memory_ids=request.memory_ids, user_id=request.user_id)
@@ -217,8 +220,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
217
220
  sort_by: Optional[str] = Query(default="updated_at", description="Field to sort memories by"),
218
221
  sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
219
222
  db_id: Optional[str] = Query(default=None, description="Database ID to query memories from"),
223
+ table: Optional[str] = Query(default=None, description="The database table to use"),
220
224
  ) -> PaginatedResponse[UserMemorySchema]:
221
- db = get_db(dbs, db_id)
225
+ db = await get_db(dbs, db_id, table)
222
226
 
223
227
  if hasattr(request.state, "user_id"):
224
228
  user_id = request.state.user_id
@@ -294,8 +298,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
294
298
  memory_id: str = Path(description="Memory ID to retrieve"),
295
299
  user_id: Optional[str] = Query(default=None, description="User ID to query memory for"),
296
300
  db_id: Optional[str] = Query(default=None, description="Database ID to query memory from"),
301
+ table: Optional[str] = Query(default=None, description="Table to query memory from"),
297
302
  ) -> UserMemorySchema:
298
- db = get_db(dbs, db_id)
303
+ db = await get_db(dbs, db_id, table)
299
304
 
300
305
  if hasattr(request.state, "user_id"):
301
306
  user_id = request.state.user_id
@@ -343,8 +348,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
343
348
  )
344
349
  async def get_topics(
345
350
  db_id: Optional[str] = Query(default=None, description="Database ID to query topics from"),
351
+ table: Optional[str] = Query(default=None, description="Table to query topics from"),
346
352
  ) -> List[str]:
347
- db = get_db(dbs, db_id)
353
+ db = await get_db(dbs, db_id, table)
348
354
  if isinstance(db, AsyncBaseDb):
349
355
  db = cast(AsyncBaseDb, db)
350
356
  return await db.get_all_memory_topics()
@@ -389,6 +395,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
389
395
  payload: UserMemoryCreateSchema,
390
396
  memory_id: str = Path(description="Memory ID to update"),
391
397
  db_id: Optional[str] = Query(default=None, description="Database ID to use for update"),
398
+ table: Optional[str] = Query(default=None, description="Table to use for update"),
392
399
  ) -> UserMemorySchema:
393
400
  if hasattr(request.state, "user_id"):
394
401
  user_id = request.state.user_id
@@ -397,7 +404,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
397
404
  if payload.user_id is None:
398
405
  raise HTTPException(status_code=400, detail="User ID is required")
399
406
 
400
- db = get_db(dbs, db_id)
407
+ db = await get_db(dbs, db_id, table)
401
408
 
402
409
  if isinstance(db, AsyncBaseDb):
403
410
  db = cast(AsyncBaseDb, db)
@@ -459,8 +466,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
459
466
  limit: Optional[int] = Query(default=20, description="Number of user statistics to return per page"),
460
467
  page: Optional[int] = Query(default=1, description="Page number for pagination"),
461
468
  db_id: Optional[str] = Query(default=None, description="Database ID to query statistics from"),
469
+ table: Optional[str] = Query(default=None, description="Table to query statistics from"),
462
470
  ) -> PaginatedResponse[UserStatsSchema]:
463
- db = get_db(dbs, db_id)
471
+ db = await get_db(dbs, db_id, table)
464
472
  try:
465
473
  if isinstance(db, AsyncBaseDb):
466
474
  db = cast(AsyncBaseDb, db)
@@ -22,7 +22,7 @@ logger = logging.getLogger(__name__)
22
22
 
23
23
 
24
24
  def get_metrics_router(
25
- dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
25
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
26
26
  ) -> APIRouter:
27
27
  """Create metrics router with comprehensive OpenAPI documentation for system metrics and analytics endpoints."""
28
28
  router = APIRouter(
@@ -39,7 +39,7 @@ def get_metrics_router(
39
39
  return attach_routes(router=router, dbs=dbs)
40
40
 
41
41
 
42
- def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
42
+ def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
43
43
  @router.get(
44
44
  "/metrics",
45
45
  response_model=MetricsResponse,
@@ -99,9 +99,10 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
99
99
  default=None, description="Ending date for metrics range (YYYY-MM-DD format)"
100
100
  ),
101
101
  db_id: Optional[str] = Query(default=None, description="Database ID to query metrics from"),
102
+ table: Optional[str] = Query(default=None, description="The database table to use"),
102
103
  ) -> MetricsResponse:
103
104
  try:
104
- db = get_db(dbs, db_id)
105
+ db = await get_db(dbs, db_id, table)
105
106
  if isinstance(db, AsyncBaseDb):
106
107
  db = cast(AsyncBaseDb, db)
107
108
  metrics, latest_updated_at = await db.get_metrics(starting_date=starting_date, ending_date=ending_date)
@@ -169,9 +170,10 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
169
170
  )
170
171
  async def calculate_metrics(
171
172
  db_id: Optional[str] = Query(default=None, description="Database ID to use for metrics calculation"),
173
+ table: Optional[str] = Query(default=None, description="Table to use for metrics calculation"),
172
174
  ) -> List[DayAggregatedMetrics]:
173
175
  try:
174
- db = get_db(dbs, db_id)
176
+ db = await get_db(dbs, db_id, table)
175
177
  if isinstance(db, AsyncBaseDb):
176
178
  db = cast(AsyncBaseDb, db)
177
179
  result = await db.calculate_metrics()
@@ -35,7 +35,7 @@ logger = logging.getLogger(__name__)
35
35
 
36
36
 
37
37
  def get_session_router(
38
- dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings()
38
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings()
39
39
  ) -> APIRouter:
40
40
  """Create session router with comprehensive OpenAPI documentation for session management endpoints."""
41
41
  session_router = APIRouter(
@@ -52,7 +52,7 @@ def get_session_router(
52
52
  return attach_routes(router=session_router, dbs=dbs)
53
53
 
54
54
 
55
- def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
55
+ def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
56
56
  @router.get(
57
57
  "/sessions",
58
58
  response_model=PaginatedResponse[SessionSchema],
@@ -89,6 +89,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
89
89
  },
90
90
  },
91
91
  400: {"description": "Invalid session type or filter parameters", "model": BadRequestResponse},
92
+ 404: {"description": "Not found", "model": NotFoundResponse},
92
93
  422: {"description": "Validation error in query parameters", "model": ValidationErrorResponse},
93
94
  },
94
95
  )
@@ -109,8 +110,12 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
109
110
  sort_by: Optional[str] = Query(default="created_at", description="Field to sort sessions by"),
110
111
  sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
111
112
  db_id: Optional[str] = Query(default=None, description="Database ID to query sessions from"),
113
+ table: Optional[str] = Query(default=None, description="The database table to use"),
112
114
  ) -> PaginatedResponse[SessionSchema]:
113
- db = get_db(dbs, db_id)
115
+ try:
116
+ db = await get_db(dbs, db_id, table)
117
+ except Exception as e:
118
+ raise HTTPException(status_code=404, detail=f"{e}")
114
119
 
115
120
  if hasattr(request.state, "user_id"):
116
121
  user_id = request.state.user_id
@@ -202,7 +207,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
202
207
  ),
203
208
  db_id: Optional[str] = Query(default=None, description="Database ID to create session in"),
204
209
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
205
- db = get_db(dbs, db_id)
210
+ db = await get_db(dbs, db_id)
206
211
 
207
212
  # Get user_id from request state if available (from auth middleware)
208
213
  user_id = create_session_request.user_id
@@ -373,8 +378,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
373
378
  ),
374
379
  user_id: Optional[str] = Query(default=None, description="User ID to query session from"),
375
380
  db_id: Optional[str] = Query(default=None, description="Database ID to query session from"),
381
+ table: Optional[str] = Query(default=None, description="Table to query session from"),
376
382
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
377
- db = get_db(dbs, db_id)
383
+ db = await get_db(dbs, db_id, table)
378
384
 
379
385
  if hasattr(request.state, "user_id"):
380
386
  user_id = request.state.user_id
@@ -528,8 +534,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
528
534
  description="Filter runs created before this Unix timestamp (epoch time in seconds)",
529
535
  ),
530
536
  db_id: Optional[str] = Query(default=None, description="Database ID to query runs from"),
537
+ table: Optional[str] = Query(default=None, description="Table to query runs from"),
531
538
  ) -> List[Union[RunSchema, TeamRunSchema, WorkflowRunSchema]]:
532
- db = get_db(dbs, db_id)
539
+ db = await get_db(dbs, db_id, table)
533
540
 
534
541
  if hasattr(request.state, "user_id"):
535
542
  user_id = request.state.user_id
@@ -644,7 +651,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
644
651
  user_id: Optional[str] = Query(default=None, description="User ID to query run from"),
645
652
  db_id: Optional[str] = Query(default=None, description="Database ID to query run from"),
646
653
  ) -> Union[RunSchema, TeamRunSchema, WorkflowRunSchema]:
647
- db = get_db(dbs, db_id)
654
+ db = await get_db(dbs, db_id)
648
655
 
649
656
  if hasattr(request.state, "user_id"):
650
657
  user_id = request.state.user_id
@@ -702,8 +709,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
702
709
  async def delete_session(
703
710
  session_id: str = Path(description="Session ID to delete"),
704
711
  db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
712
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
705
713
  ) -> None:
706
- db = get_db(dbs, db_id)
714
+ db = await get_db(dbs, db_id, table)
707
715
  if isinstance(db, AsyncBaseDb):
708
716
  db = cast(AsyncBaseDb, db)
709
717
  await db.delete_session(session_id=session_id)
@@ -734,11 +742,12 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
734
742
  default=SessionType.AGENT, description="Default session type filter", alias="type"
735
743
  ),
736
744
  db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
745
+ table: Optional[str] = Query(default=None, description="Table to use for deletion"),
737
746
  ) -> None:
738
747
  if len(request.session_ids) != len(request.session_types):
739
748
  raise HTTPException(status_code=400, detail="Session IDs and session types must have the same length")
740
749
 
741
- db = get_db(dbs, db_id)
750
+ db = await get_db(dbs, db_id, table)
742
751
  if isinstance(db, AsyncBaseDb):
743
752
  db = cast(AsyncBaseDb, db)
744
753
  await db.delete_sessions(session_ids=request.session_ids)
@@ -840,8 +849,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
840
849
  ),
841
850
  session_name: str = Body(embed=True, description="New name for the session"),
842
851
  db_id: Optional[str] = Query(default=None, description="Database ID to use for rename operation"),
852
+ table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
843
853
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
844
- db = get_db(dbs, db_id)
854
+ db = await get_db(dbs, db_id, table)
845
855
  if isinstance(db, AsyncBaseDb):
846
856
  db = cast(AsyncBaseDb, db)
847
857
  session = await db.rename_session(
@@ -926,7 +936,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
926
936
  user_id: Optional[str] = Query(default=None, description="User ID"),
927
937
  db_id: Optional[str] = Query(default=None, description="Database ID to use for update operation"),
928
938
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
929
- db = get_db(dbs, db_id)
939
+ db = await get_db(dbs, db_id)
930
940
 
931
941
  if hasattr(request.state, "user_id"):
932
942
  user_id = request.state.user_id
agno/os/utils.py CHANGED
@@ -19,23 +19,69 @@ from agno.utils.log import logger
19
19
  from agno.workflow.workflow import Workflow
20
20
 
21
21
 
22
- def get_db(dbs: dict[str, Union[BaseDb, AsyncBaseDb]], db_id: Optional[str] = None) -> Union[BaseDb, AsyncBaseDb]:
23
- """Return the database with the given ID, or the first database if no ID is provided."""
22
+ async def get_db(
23
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], db_id: Optional[str] = None, table: Optional[str] = None
24
+ ) -> Union[BaseDb, AsyncBaseDb]:
25
+ """Return the database with the given ID and/or table, or the first database if no ID/table is provided."""
26
+
27
+ if table and not db_id:
28
+ raise HTTPException(status_code=400, detail="The db_id query parameter is required when passing a table")
29
+
30
+ async def _has_table(db: Union[BaseDb, AsyncBaseDb], table_name: str) -> bool:
31
+ """Check if this database has the specified table (configured and actually exists)."""
32
+ # First check if table name is configured
33
+ is_configured = (
34
+ hasattr(db, "session_table_name")
35
+ and db.session_table_name == table_name
36
+ or hasattr(db, "memory_table_name")
37
+ and db.memory_table_name == table_name
38
+ or hasattr(db, "metrics_table_name")
39
+ and db.metrics_table_name == table_name
40
+ or hasattr(db, "eval_table_name")
41
+ and db.eval_table_name == table_name
42
+ or hasattr(db, "knowledge_table_name")
43
+ and db.knowledge_table_name == table_name
44
+ )
45
+
46
+ if not is_configured:
47
+ return False
48
+
49
+ # Then check if table actually exists in the database
50
+ try:
51
+ if isinstance(db, AsyncBaseDb):
52
+ # For async databases, await the check
53
+ return await db.table_exists(table_name)
54
+ else:
55
+ # For sync databases, call directly
56
+ return db.table_exists(table_name)
57
+ except (NotImplementedError, AttributeError):
58
+ # If table_exists not implemented, fall back to configuration check
59
+ return is_configured
60
+
61
+ # If db_id is provided, first find the database with that ID
62
+ if db_id:
63
+ target_db_list = dbs.get(db_id)
64
+ if not target_db_list:
65
+ raise HTTPException(status_code=404, detail=f"No database found with id '{db_id}'")
66
+
67
+ # If table is also specified, search through all databases with this ID to find one with the table
68
+ if table:
69
+ for db in target_db_list:
70
+ if await _has_table(db, table):
71
+ return db
72
+ raise HTTPException(status_code=404, detail=f"No database with id '{db_id}' has table '{table}'")
73
+
74
+ # If no table specified, return the first database with this ID
75
+ return target_db_list[0]
24
76
 
25
77
  # Raise if multiple databases are provided but no db_id is provided
26
- if not db_id and len(dbs) > 1:
78
+ if len(dbs) > 1:
27
79
  raise HTTPException(
28
80
  status_code=400, detail="The db_id query parameter is required when using multiple databases"
29
81
  )
30
82
 
31
- # Get and return the database with the given ID, or raise if not found
32
- if db_id:
33
- db = dbs.get(db_id)
34
- if not db:
35
- raise HTTPException(status_code=404, detail=f"Database with id '{db_id}' not found")
36
- else:
37
- db = next(iter(dbs.values()))
38
- return db
83
+ # Return the first (and only) database
84
+ return next(db for dbs in dbs.values() for db in dbs)
39
85
 
40
86
 
41
87
  def get_knowledge_instance_by_db_id(knowledge_instances: List[Knowledge], db_id: Optional[str] = None) -> Knowledge:
agno/team/team.py CHANGED
@@ -802,13 +802,10 @@ class Team:
802
802
  member.team_id = self.id
803
803
  member.set_id()
804
804
 
805
- # Inherit team models if agent has no explicit model
806
- for model_type in ["model", "reasoning_model", "parser_model", "output_model"]:
807
- if getattr(member, model_type) is None and getattr(self, model_type) is not None:
808
- setattr(member, model_type, getattr(self, model_type))
809
- log_info(
810
- f"Agent '{member.name or member.id}' inheriting {model_type} from Team: {getattr(self, model_type).id}"
811
- )
805
+ # Inherit team primary model if agent has no explicit model
806
+ if member.model is None and self.model is not None:
807
+ member.model = self.model
808
+ log_info(f"Agent '{member.name or member.id}' inheriting model from Team: {self.model.id}")
812
809
 
813
810
  elif isinstance(member, Team):
814
811
  member.parent_team_id = self.id
@@ -1458,7 +1455,7 @@ class Team:
1458
1455
  add_session_state_to_context: Optional[bool] = None,
1459
1456
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
1460
1457
  stream_events: bool = False,
1461
- yield_run_response: bool = False,
1458
+ yield_run_output: bool = False,
1462
1459
  debug_mode: Optional[bool] = None,
1463
1460
  **kwargs: Any,
1464
1461
  ) -> Iterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]:
@@ -1701,7 +1698,7 @@ class Team:
1701
1698
  if stream_events:
1702
1699
  yield completed_event
1703
1700
 
1704
- if yield_run_response:
1701
+ if yield_run_output:
1705
1702
  yield run_response
1706
1703
 
1707
1704
  # Log Team Telemetry
@@ -1778,7 +1775,8 @@ class Team:
1778
1775
  dependencies: Optional[Dict[str, Any]] = None,
1779
1776
  metadata: Optional[Dict[str, Any]] = None,
1780
1777
  debug_mode: Optional[bool] = None,
1781
- yield_run_response: bool = False,
1778
+ yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
1779
+ yield_run_output: bool = False,
1782
1780
  **kwargs: Any,
1783
1781
  ) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...
1784
1782
 
@@ -1804,7 +1802,8 @@ class Team:
1804
1802
  dependencies: Optional[Dict[str, Any]] = None,
1805
1803
  metadata: Optional[Dict[str, Any]] = None,
1806
1804
  debug_mode: Optional[bool] = None,
1807
- yield_run_response: bool = False,
1805
+ yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
1806
+ yield_run_output: bool = False,
1808
1807
  **kwargs: Any,
1809
1808
  ) -> Union[TeamRunOutput, Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
1810
1809
  """Run the Team and return the response."""
@@ -1948,6 +1947,8 @@ class Team:
1948
1947
  last_exception = None
1949
1948
  num_attempts = retries + 1
1950
1949
 
1950
+ yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
1951
+
1951
1952
  for attempt in range(num_attempts):
1952
1953
  # Initialize the current run
1953
1954
 
@@ -1964,7 +1965,7 @@ class Team:
1964
1965
  add_session_state_to_context=add_session_state,
1965
1966
  response_format=response_format,
1966
1967
  stream_events=stream_events,
1967
- yield_run_response=yield_run_response,
1968
+ yield_run_output=yield_run_output,
1968
1969
  debug_mode=debug_mode,
1969
1970
  **kwargs,
1970
1971
  )
@@ -2270,7 +2271,7 @@ class Team:
2270
2271
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
2271
2272
  stream_events: bool = False,
2272
2273
  stream_intermediate_steps: bool = False,
2273
- yield_run_response: bool = False,
2274
+ yield_run_output: bool = False,
2274
2275
  add_dependencies_to_context: Optional[bool] = None,
2275
2276
  add_session_state_to_context: Optional[bool] = None,
2276
2277
  add_history_to_context: Optional[bool] = None,
@@ -2545,7 +2546,7 @@ class Team:
2545
2546
  if stream_events:
2546
2547
  yield completed_event
2547
2548
 
2548
- if yield_run_response:
2549
+ if yield_run_output:
2549
2550
  yield run_response
2550
2551
 
2551
2552
  # Log Team Telemetry
@@ -2631,7 +2632,8 @@ class Team:
2631
2632
  dependencies: Optional[Dict[str, Any]] = None,
2632
2633
  metadata: Optional[Dict[str, Any]] = None,
2633
2634
  debug_mode: Optional[bool] = None,
2634
- yield_run_response: bool = False,
2635
+ yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
2636
+ yield_run_output: bool = False,
2635
2637
  **kwargs: Any,
2636
2638
  ) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...
2637
2639
 
@@ -2657,7 +2659,8 @@ class Team:
2657
2659
  dependencies: Optional[Dict[str, Any]] = None,
2658
2660
  metadata: Optional[Dict[str, Any]] = None,
2659
2661
  debug_mode: Optional[bool] = None,
2660
- yield_run_response: bool = False,
2662
+ yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
2663
+ yield_run_output: bool = False,
2661
2664
  **kwargs: Any,
2662
2665
  ) -> Union[TeamRunOutput, AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
2663
2666
  """Run the Team asynchronously and return the response."""
@@ -2783,6 +2786,8 @@ class Team:
2783
2786
  last_exception = None
2784
2787
  num_attempts = retries + 1
2785
2788
 
2789
+ yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
2790
+
2786
2791
  for attempt in range(num_attempts):
2787
2792
  # Run the team
2788
2793
  try:
@@ -2798,7 +2803,7 @@ class Team:
2798
2803
  add_session_state_to_context=add_session_state,
2799
2804
  response_format=response_format,
2800
2805
  stream_events=stream_events,
2801
- yield_run_response=yield_run_response,
2806
+ yield_run_output=yield_run_output,
2802
2807
  debug_mode=debug_mode,
2803
2808
  **kwargs,
2804
2809
  )
@@ -6988,7 +6993,7 @@ class Team:
6988
6993
  knowledge_filters=run_context.knowledge_filters
6989
6994
  if not member_agent.knowledge_filters and member_agent.knowledge
6990
6995
  else None,
6991
- yield_run_response=True,
6996
+ yield_run_output=True,
6992
6997
  )
6993
6998
  member_agent_run_response = None
6994
6999
  for member_agent_run_output_event in member_agent_run_response_stream:
@@ -7118,7 +7123,7 @@ class Team:
7118
7123
  knowledge_filters=run_context.knowledge_filters
7119
7124
  if not member_agent.knowledge_filters and member_agent.knowledge
7120
7125
  else None,
7121
- yield_run_response=True,
7126
+ yield_run_output=True,
7122
7127
  )
7123
7128
  member_agent_run_response = None
7124
7129
  async for member_agent_run_response_event in member_agent_run_response_stream:
@@ -7234,7 +7239,7 @@ class Team:
7234
7239
  add_dependencies_to_context=add_dependencies_to_context,
7235
7240
  add_session_state_to_context=add_session_state_to_context,
7236
7241
  metadata=run_context.metadata,
7237
- yield_run_response=True,
7242
+ yield_run_output=True,
7238
7243
  )
7239
7244
  member_agent_run_response = None
7240
7245
  for member_agent_run_response_chunk in member_agent_run_response_stream:
@@ -7350,7 +7355,7 @@ class Team:
7350
7355
  add_dependencies_to_context=add_dependencies_to_context,
7351
7356
  add_session_state_to_context=add_session_state_to_context,
7352
7357
  metadata=run_context.metadata,
7353
- yield_run_response=True,
7358
+ yield_run_output=True,
7354
7359
  )
7355
7360
  member_agent_run_response = None
7356
7361
  try:
@@ -1,3 +1,9 @@
1
1
  from agno.vectordb.mongodb.mongodb import MongoDb
2
2
 
3
- __all__ = ["MongoDb"]
3
+ # Alias to avoid name collision with the main MongoDb class
4
+ MongoVectorDb = MongoDb
5
+
6
+ __all__ = [
7
+ "MongoVectorDb",
8
+ "MongoDb",
9
+ ]
@@ -1,5 +1,9 @@
1
1
  from agno.vectordb.redis.redisdb import RedisDB
2
2
 
3
+ # Backward compatibility alias
4
+ RedisVectorDb = RedisDB
5
+
3
6
  __all__ = [
7
+ "RedisVectorDb",
4
8
  "RedisDB",
5
9
  ]