agno 2.0.2__py3-none-any.whl → 2.0.4__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 (63) hide show
  1. agno/agent/agent.py +164 -87
  2. agno/db/dynamo/dynamo.py +8 -0
  3. agno/db/firestore/firestore.py +8 -1
  4. agno/db/gcs_json/gcs_json_db.py +9 -0
  5. agno/db/json/json_db.py +8 -0
  6. agno/db/mongo/mongo.py +10 -1
  7. agno/db/mysql/mysql.py +10 -0
  8. agno/db/postgres/postgres.py +16 -8
  9. agno/db/redis/redis.py +6 -0
  10. agno/db/singlestore/schemas.py +1 -1
  11. agno/db/singlestore/singlestore.py +8 -1
  12. agno/db/sqlite/sqlite.py +9 -1
  13. agno/db/utils.py +14 -0
  14. agno/knowledge/chunking/fixed.py +1 -1
  15. agno/knowledge/knowledge.py +91 -65
  16. agno/knowledge/reader/base.py +3 -0
  17. agno/knowledge/reader/csv_reader.py +1 -1
  18. agno/knowledge/reader/json_reader.py +1 -1
  19. agno/knowledge/reader/markdown_reader.py +5 -5
  20. agno/knowledge/reader/s3_reader.py +0 -12
  21. agno/knowledge/reader/text_reader.py +5 -5
  22. agno/models/base.py +2 -2
  23. agno/models/cerebras/cerebras.py +5 -3
  24. agno/models/cerebras/cerebras_openai.py +5 -3
  25. agno/models/google/gemini.py +33 -11
  26. agno/models/litellm/chat.py +1 -1
  27. agno/models/openai/chat.py +3 -0
  28. agno/models/openai/responses.py +81 -40
  29. agno/models/response.py +5 -0
  30. agno/models/siliconflow/__init__.py +5 -0
  31. agno/models/siliconflow/siliconflow.py +25 -0
  32. agno/os/app.py +4 -1
  33. agno/os/auth.py +24 -14
  34. agno/os/interfaces/slack/router.py +1 -1
  35. agno/os/interfaces/whatsapp/router.py +2 -0
  36. agno/os/router.py +187 -76
  37. agno/os/routers/evals/utils.py +9 -9
  38. agno/os/routers/health.py +26 -0
  39. agno/os/routers/knowledge/knowledge.py +11 -11
  40. agno/os/routers/session/session.py +24 -8
  41. agno/os/schema.py +8 -2
  42. agno/run/agent.py +5 -2
  43. agno/run/base.py +6 -3
  44. agno/run/team.py +11 -3
  45. agno/run/workflow.py +69 -12
  46. agno/session/team.py +1 -0
  47. agno/team/team.py +196 -93
  48. agno/tools/mcp.py +1 -0
  49. agno/tools/mem0.py +11 -17
  50. agno/tools/memory.py +419 -0
  51. agno/tools/workflow.py +279 -0
  52. agno/utils/audio.py +27 -0
  53. agno/utils/common.py +90 -1
  54. agno/utils/print_response/agent.py +6 -2
  55. agno/utils/streamlit.py +14 -8
  56. agno/vectordb/chroma/chromadb.py +8 -2
  57. agno/workflow/step.py +111 -13
  58. agno/workflow/workflow.py +16 -13
  59. {agno-2.0.2.dist-info → agno-2.0.4.dist-info}/METADATA +1 -1
  60. {agno-2.0.2.dist-info → agno-2.0.4.dist-info}/RECORD +63 -58
  61. {agno-2.0.2.dist-info → agno-2.0.4.dist-info}/WHEEL +0 -0
  62. {agno-2.0.2.dist-info → agno-2.0.4.dist-info}/licenses/LICENSE +0 -0
  63. {agno-2.0.2.dist-info → agno-2.0.4.dist-info}/top_level.txt +0 -0
agno/team/team.py CHANGED
@@ -55,6 +55,7 @@ from agno.run.team import TeamRunEvent, TeamRunInput, TeamRunOutput, TeamRunOutp
55
55
  from agno.session import SessionSummaryManager, TeamSession
56
56
  from agno.tools import Toolkit
57
57
  from agno.tools.function import Function
58
+ from agno.utils.common import is_typed_dict, validate_typed_dict
58
59
  from agno.utils.events import (
59
60
  create_team_memory_update_completed_event,
60
61
  create_team_memory_update_started_event,
@@ -408,6 +409,7 @@ class Team:
408
409
  enable_agentic_memory: bool = False,
409
410
  enable_user_memories: bool = False,
410
411
  add_memories_to_context: Optional[bool] = None,
412
+ memory_manager: Optional[MemoryManager] = None,
411
413
  enable_session_summaries: bool = False,
412
414
  session_summary_manager: Optional[SessionSummaryManager] = None,
413
415
  add_session_summary_to_context: Optional[bool] = None,
@@ -505,6 +507,7 @@ class Team:
505
507
  self.enable_agentic_memory = enable_agentic_memory
506
508
  self.enable_user_memories = enable_user_memories
507
509
  self.add_memories_to_context = add_memories_to_context
510
+ self.memory_manager = memory_manager
508
511
  self.enable_session_summaries = enable_session_summaries
509
512
  self.session_summary_manager = session_summary_manager
510
513
  self.add_session_summary_to_context = add_session_summary_to_context
@@ -619,8 +622,6 @@ class Team:
619
622
  if isinstance(input, BaseModel):
620
623
  if isinstance(input, self.input_schema):
621
624
  try:
622
- # Re-validate to catch any field validation errors
623
- input.model_validate(input.model_dump())
624
625
  return input
625
626
  except Exception as e:
626
627
  raise ValueError(f"BaseModel validation failed: {str(e)}")
@@ -631,8 +632,13 @@ class Team:
631
632
  # Case 2: Message is a dict
632
633
  elif isinstance(input, dict):
633
634
  try:
634
- validated_model = self.input_schema(**input)
635
- return validated_model
635
+ # Check if the schema is a TypedDict
636
+ if is_typed_dict(self.input_schema):
637
+ validated_dict = validate_typed_dict(input, self.input_schema)
638
+ return validated_dict
639
+ else:
640
+ validated_model = self.input_schema(**input)
641
+ return validated_model
636
642
  except Exception as e:
637
643
  raise ValueError(f"Failed to parse dict into {self.input_schema.__name__}: {str(e)}")
638
644
 
@@ -804,9 +810,9 @@ class Team:
804
810
  1. Reason about the task(s) if reasoning is enabled
805
811
  2. Get a response from the model
806
812
  3. Update Team Memory
807
- 5. Save session to storage
808
- 6. Parse any structured outputs
809
- 7. Log the team run
813
+ 4. Add RunOutput to Team Session
814
+ 5. Calculate session metrics
815
+ 6. Save session to storage
810
816
  """
811
817
  log_debug(f"Team Run Start: {run_response.run_id}", center=True)
812
818
 
@@ -847,10 +853,7 @@ class Team:
847
853
  else:
848
854
  self._scrub_media_from_run_output(run_response)
849
855
 
850
- # 4. Add the RunOutput to Team Session
851
- session.upsert_run(run_response=run_response)
852
-
853
- # 5. Update Team Memory
856
+ # 3. Update Team Memory
854
857
  response_iterator = self._make_memories_and_summaries(
855
858
  run_response=run_response,
856
859
  run_messages=run_messages,
@@ -859,14 +862,17 @@ class Team:
859
862
  )
860
863
  deque(response_iterator, maxlen=0)
861
864
 
862
- # 5. Calculate session metrics
863
- self._update_session_metrics(session=session)
864
-
865
865
  run_response.status = RunStatus.completed
866
866
 
867
- # 5. Parse team response model
867
+ # Parse team response model
868
868
  self._convert_response_to_structured_format(run_response=run_response)
869
869
 
870
+ # 4. Add the RunOutput to Team Session
871
+ session.upsert_run(run_response=run_response)
872
+
873
+ # 5. Calculate session metrics
874
+ self._update_session_metrics(session=session)
875
+
870
876
  # 6. Save session to storage
871
877
  self.save_session(session=session)
872
878
 
@@ -897,8 +903,9 @@ class Team:
897
903
  1. Reason about the task(s) if reasoning is enabled
898
904
  2. Get a response from the model
899
905
  3. Update Team Memory
900
- 4. Save session to storage
901
- 5. Log Team Run
906
+ 4. Add RunOutput to Team Session
907
+ 5. Calculate session metrics
908
+ 6. Save session to storage
902
909
  """
903
910
 
904
911
  log_debug(f"Team Run Start: {run_response.run_id}", center=True)
@@ -971,10 +978,7 @@ class Team:
971
978
  session=session, run_response=run_response, stream_intermediate_steps=stream_intermediate_steps
972
979
  )
973
980
 
974
- # 4. Add the run to memory
975
- session.upsert_run(run_response=run_response)
976
-
977
- # 5. Update Team Memory
981
+ # 3. Update Team Memory
978
982
  yield from self._make_memories_and_summaries(
979
983
  run_response=run_response,
980
984
  run_messages=run_messages,
@@ -982,11 +986,14 @@ class Team:
982
986
  user_id=user_id,
983
987
  )
984
988
 
989
+ run_response.status = RunStatus.completed
990
+
991
+ # 4. Add the run to memory
992
+ session.upsert_run(run_response=run_response)
993
+
985
994
  # 5. Calculate session metrics
986
995
  self._update_session_metrics(session=session)
987
996
 
988
- run_response.status = RunStatus.completed
989
-
990
997
  completed_event = self._handle_event(
991
998
  create_team_run_completed_event(
992
999
  from_run_response=run_response,
@@ -1336,35 +1343,72 @@ class Team:
1336
1343
  async def _arun(
1337
1344
  self,
1338
1345
  run_response: TeamRunOutput,
1339
- run_messages: RunMessages,
1346
+ input_message: Union[str, List, Dict, Message, BaseModel, List[Message]],
1340
1347
  session: TeamSession,
1348
+ session_state: Optional[Dict[str, Any]] = None,
1341
1349
  user_id: Optional[str] = None,
1350
+ images: Optional[Sequence[Image]] = None,
1351
+ videos: Optional[Sequence[Video]] = None,
1352
+ audio: Optional[Sequence[Audio]] = None,
1353
+ files: Optional[Sequence[File]] = None,
1354
+ knowledge_filters: Optional[Dict[str, Any]] = None,
1355
+ add_history_to_context: Optional[bool] = None,
1356
+ add_dependencies_to_context: Optional[bool] = None,
1357
+ add_session_state_to_context: Optional[bool] = None,
1358
+ metadata: Optional[Dict[str, Any]] = None,
1342
1359
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
1360
+ dependencies: Optional[Dict[str, Any]] = None,
1361
+ **kwargs: Any,
1343
1362
  ) -> TeamRunOutput:
1344
1363
  """Run the Team and return the response.
1345
1364
 
1346
1365
  Steps:
1347
- 1. Reason about the task(s) if reasoning is enabled
1348
- 2. Get a response from the model
1349
- 3. Update Team Memory
1350
- 5. Save session to storage
1351
- 6. Parse any structured outputs
1352
- 7. Log the team run
1366
+ 1. Resolve dependencies
1367
+ 2. Prepare run messages
1368
+ 3. Reason about the task(s) if reasoning is enabled
1369
+ 4. Get a response from the model
1370
+ 5. Update Team Memory
1371
+ 6. Add RunOutput to Team Session
1372
+ 7. Calculate session metrics
1373
+ 8. Save session to storage
1353
1374
  """
1354
- self.model = cast(Model, self.model)
1375
+ # 1. Resolve callable dependencies if present
1376
+ if dependencies is not None:
1377
+ await self._aresolve_run_dependencies(dependencies=dependencies)
1355
1378
 
1379
+ # 2. Prepare run messages
1380
+ run_messages = self._get_run_messages(
1381
+ run_response=run_response,
1382
+ session=session,
1383
+ session_state=session_state,
1384
+ user_id=user_id,
1385
+ input_message=input_message,
1386
+ audio=audio,
1387
+ images=images,
1388
+ videos=videos,
1389
+ files=files,
1390
+ knowledge_filters=knowledge_filters,
1391
+ add_history_to_context=add_history_to_context,
1392
+ dependencies=dependencies,
1393
+ add_dependencies_to_context=add_dependencies_to_context,
1394
+ add_session_state_to_context=add_session_state_to_context,
1395
+ metadata=metadata,
1396
+ **kwargs,
1397
+ )
1398
+
1399
+ self.model = cast(Model, self.model)
1356
1400
  log_debug(f"Team Run Start: {run_response.run_id}", center=True)
1357
1401
 
1358
1402
  # Register run for cancellation tracking
1359
1403
  register_run(run_response.run_id) # type: ignore
1360
1404
 
1361
- # 1. Reason about the task(s) if reasoning is enabled
1405
+ # 3. Reason about the task(s) if reasoning is enabled
1362
1406
  await self._ahandle_reasoning(run_response=run_response, run_messages=run_messages)
1363
1407
 
1364
1408
  # Check for cancellation before model call
1365
1409
  raise_if_cancelled(run_response.run_id) # type: ignore
1366
1410
 
1367
- # 2. Get the model response for the team leader
1411
+ # 4. Get the model response for the team leader
1368
1412
  model_response = await self.model.aresponse(
1369
1413
  messages=run_messages.messages,
1370
1414
  tools=self._tools_for_model,
@@ -1391,10 +1435,7 @@ class Team:
1391
1435
  else:
1392
1436
  self._scrub_media_from_run_output(run_response)
1393
1437
 
1394
- # 3. Add the run to memory
1395
- session.upsert_run(run_response=run_response)
1396
-
1397
- # 4. Update Team Memory
1438
+ # 5. Update Team Memory
1398
1439
  async for _ in self._amake_memories_and_summaries(
1399
1440
  run_response=run_response,
1400
1441
  session=session,
@@ -1403,18 +1444,21 @@ class Team:
1403
1444
  ):
1404
1445
  pass
1405
1446
 
1406
- # 5. Calculate session metrics
1407
- self._update_session_metrics(session=session)
1408
-
1409
1447
  run_response.status = RunStatus.completed
1410
1448
 
1411
- # 6. Parse team response model
1449
+ # Parse team response model
1412
1450
  self._convert_response_to_structured_format(run_response=run_response)
1413
1451
 
1414
- # 7. Save session to storage
1452
+ # 6. Add the run to memory
1453
+ session.upsert_run(run_response=run_response)
1454
+
1455
+ # 7. Calculate session metrics
1456
+ self._update_session_metrics(session=session)
1457
+
1458
+ # 8. Save session to storage
1415
1459
  self.save_session(session=session)
1416
1460
 
1417
- # 8. Log Team Telemetry
1461
+ # Log Team Telemetry
1418
1462
  await self._alog_team_telemetry(session_id=session.session_id, run_id=run_response.run_id)
1419
1463
 
1420
1464
  log_debug(f"Team Run End: {run_response.run_id}", center=True, symbol="*")
@@ -1427,25 +1471,64 @@ class Team:
1427
1471
  async def _arun_stream(
1428
1472
  self,
1429
1473
  run_response: TeamRunOutput,
1430
- run_messages: RunMessages,
1474
+ input_message: Union[str, List, Dict, Message, BaseModel, List[Message]],
1431
1475
  session: TeamSession,
1476
+ session_state: Optional[Dict[str, Any]] = None,
1432
1477
  user_id: Optional[str] = None,
1478
+ images: Optional[Sequence[Image]] = None,
1479
+ videos: Optional[Sequence[Video]] = None,
1480
+ audio: Optional[Sequence[Audio]] = None,
1481
+ files: Optional[Sequence[File]] = None,
1482
+ knowledge_filters: Optional[Dict[str, Any]] = None,
1483
+ add_history_to_context: Optional[bool] = None,
1484
+ add_dependencies_to_context: Optional[bool] = None,
1485
+ add_session_state_to_context: Optional[bool] = None,
1486
+ metadata: Optional[Dict[str, Any]] = None,
1433
1487
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
1488
+ dependencies: Optional[Dict[str, Any]] = None,
1434
1489
  stream_intermediate_steps: bool = False,
1435
1490
  workflow_context: Optional[Dict] = None,
1436
1491
  yield_run_response: bool = False,
1492
+ **kwargs: Any,
1437
1493
  ) -> AsyncIterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]:
1438
1494
  """Run the Team and return the response.
1439
1495
 
1440
1496
  Steps:
1441
- 1. Reason about the task(s) if reasoning is enabled
1442
- 2. Get a response from the model
1443
- 3. Update Team Memory
1444
- 4. Save session to storage
1445
- 5. Log Team Run
1497
+ 1. Resolve dependencies
1498
+ 2. Prepare run messages
1499
+ 3. Reason about the task(s) if reasoning is enabled
1500
+ 4. Get a response from the model
1501
+ 5. Update Team Memory
1502
+ 6. Add RunOutput to Team Session
1503
+ 7. Calculate session metrics
1504
+ 8. Save session to storage
1446
1505
  """
1447
- log_debug(f"Team Run Start: {run_response.run_id}", center=True)
1448
1506
 
1507
+ # 1. Resolve callable dependencies if present
1508
+ if dependencies is not None:
1509
+ await self._aresolve_run_dependencies(dependencies=dependencies)
1510
+
1511
+ # 2. Prepare run messages
1512
+ run_messages = self._get_run_messages(
1513
+ run_response=run_response,
1514
+ session=session,
1515
+ session_state=session_state,
1516
+ user_id=user_id,
1517
+ input_message=input_message,
1518
+ audio=audio,
1519
+ images=images,
1520
+ videos=videos,
1521
+ files=files,
1522
+ knowledge_filters=knowledge_filters,
1523
+ add_history_to_context=add_history_to_context,
1524
+ dependencies=dependencies,
1525
+ add_dependencies_to_context=add_dependencies_to_context,
1526
+ add_session_state_to_context=add_session_state_to_context,
1527
+ metadata=metadata,
1528
+ **kwargs,
1529
+ )
1530
+
1531
+ log_debug(f"Team Run Start: {run_response.run_id}", center=True)
1449
1532
  # Register run for cancellation tracking
1450
1533
  register_run(run_response.run_id) # type: ignore
1451
1534
 
@@ -1456,7 +1539,7 @@ class Team:
1456
1539
  create_team_run_started_event(from_run_response=run_response), run_response, workflow_context
1457
1540
  )
1458
1541
 
1459
- # 1. Reason about the task(s) if reasoning is enabled
1542
+ # 3. Reason about the task(s) if reasoning is enabled
1460
1543
  async for item in self._ahandle_reasoning_stream(run_response=run_response, run_messages=run_messages):
1461
1544
  raise_if_cancelled(run_response.run_id) # type: ignore
1462
1545
  yield item
@@ -1464,7 +1547,7 @@ class Team:
1464
1547
  # Check for cancellation before model processing
1465
1548
  raise_if_cancelled(run_response.run_id) # type: ignore
1466
1549
 
1467
- # 2. Get a response from the model
1550
+ # 4. Get a response from the model
1468
1551
  if self.output_model is None:
1469
1552
  async for event in self._ahandle_model_response_stream(
1470
1553
  session=session,
@@ -1516,10 +1599,7 @@ class Team:
1516
1599
  ):
1517
1600
  yield event
1518
1601
 
1519
- # 3. Add the run to memory
1520
- session.upsert_run(run_response=run_response)
1521
-
1522
- # 4. Update Team Memory
1602
+ # 6. Update Team Memory
1523
1603
  async for event in self._amake_memories_and_summaries(
1524
1604
  run_response=run_response,
1525
1605
  session=session,
@@ -1528,16 +1608,19 @@ class Team:
1528
1608
  ):
1529
1609
  yield event
1530
1610
 
1531
- # 5. Calculate session metrics
1532
- self._update_session_metrics(session=session)
1533
-
1534
1611
  run_response.status = RunStatus.completed
1535
1612
 
1613
+ # 7. Add the run to memory
1614
+ session.upsert_run(run_response=run_response)
1615
+
1616
+ # 8. Calculate session metrics
1617
+ self._update_session_metrics(session=session)
1618
+
1536
1619
  completed_event = self._handle_event(
1537
1620
  create_team_run_completed_event(from_run_response=run_response), run_response, workflow_context
1538
1621
  )
1539
1622
 
1540
- # 6. Save session to storage
1623
+ # 9. Save session to storage
1541
1624
  self.save_session(session=session)
1542
1625
 
1543
1626
  if stream_intermediate_steps:
@@ -1546,7 +1629,7 @@ class Team:
1546
1629
  if yield_run_response:
1547
1630
  yield run_response
1548
1631
 
1549
- # 7. Log Team Telemetry
1632
+ # Log Team Telemetry
1550
1633
  await self._alog_team_telemetry(session_id=session.session_id, run_id=run_response.run_id)
1551
1634
 
1552
1635
  log_debug(f"Team Run End: {run_response.run_id}", center=True, symbol="*")
@@ -1679,10 +1762,6 @@ class Team:
1679
1762
  # Determine run dependencies (runtime override takes priority)
1680
1763
  run_dependencies = dependencies if dependencies is not None else self.dependencies
1681
1764
 
1682
- # Resolve callable dependencies if present
1683
- if run_dependencies is not None:
1684
- self._resolve_run_dependencies(dependencies=run_dependencies)
1685
-
1686
1765
  # Determine runtime context parameters
1687
1766
  add_dependencies = (
1688
1767
  add_dependencies_to_context if add_dependencies_to_context is not None else self.add_dependencies_to_context
@@ -1779,43 +1858,49 @@ class Team:
1779
1858
  for attempt in range(num_attempts):
1780
1859
  # Run the team
1781
1860
  try:
1782
- run_messages = self._get_run_messages(
1783
- run_response=run_response,
1784
- session=team_session, # type: ignore
1785
- session_state=session_state,
1786
- user_id=user_id,
1787
- input_message=validated_input,
1788
- audio=audio,
1789
- images=images,
1790
- videos=videos,
1791
- files=files,
1792
- knowledge_filters=effective_filters,
1793
- add_history_to_context=add_history,
1794
- dependencies=run_dependencies,
1795
- add_dependencies_to_context=add_dependencies,
1796
- add_session_state_to_context=add_session_state,
1797
- **kwargs,
1798
- )
1799
-
1800
1861
  if stream:
1801
1862
  response_iterator = self._arun_stream(
1802
1863
  run_response=run_response,
1803
- run_messages=run_messages,
1864
+ input_message=validated_input,
1804
1865
  session=team_session, # type: ignore
1866
+ session_state=session_state,
1805
1867
  user_id=user_id,
1868
+ audio=audio,
1869
+ images=images,
1870
+ videos=videos,
1871
+ files=files,
1872
+ knowledge_filters=effective_filters,
1873
+ add_history_to_context=add_history,
1874
+ add_dependencies_to_context=add_dependencies,
1875
+ add_session_state_to_context=add_session_state,
1876
+ metadata=metadata,
1806
1877
  response_format=response_format,
1878
+ dependencies=run_dependencies,
1807
1879
  stream_intermediate_steps=stream_intermediate_steps,
1808
1880
  workflow_context=workflow_context,
1809
1881
  yield_run_response=yield_run_response,
1882
+ **kwargs,
1810
1883
  )
1811
1884
  return response_iterator # type: ignore
1812
1885
  else:
1813
1886
  return self._arun( # type: ignore
1814
1887
  run_response=run_response,
1815
- run_messages=run_messages,
1888
+ input_message=validated_input,
1816
1889
  session=team_session, # type: ignore
1817
1890
  user_id=user_id,
1891
+ session_state=session_state,
1892
+ audio=audio,
1893
+ images=images,
1894
+ videos=videos,
1895
+ files=files,
1896
+ knowledge_filters=effective_filters,
1897
+ add_history_to_context=add_history,
1898
+ add_dependencies_to_context=add_dependencies,
1899
+ add_session_state_to_context=add_session_state,
1900
+ metadata=metadata,
1818
1901
  response_format=response_format,
1902
+ dependencies=run_dependencies,
1903
+ **kwargs,
1819
1904
  )
1820
1905
 
1821
1906
  except ModelProviderError as e:
@@ -2282,11 +2367,13 @@ class Team:
2282
2367
  tc.tool_call_id: i for i, tc in enumerate(run_response.tools) if tc.tool_call_id is not None
2283
2368
  }
2284
2369
  # Process tool calls
2285
- for tool_call_dict in tool_executions_list:
2286
- tool_call_id = tool_call_dict.tool_call_id or ""
2370
+ for tool_execution in tool_executions_list:
2371
+ tool_call_id = tool_execution.tool_call_id or ""
2287
2372
  index = tool_call_index_map.get(tool_call_id)
2288
2373
  if index is not None:
2289
- run_response.tools[index] = tool_call_dict
2374
+ if run_response.tools[index].child_run_id is not None:
2375
+ tool_execution.child_run_id = run_response.tools[index].child_run_id
2376
+ run_response.tools[index] = tool_execution
2290
2377
  else:
2291
2378
  run_response.tools = tool_executions_list
2292
2379
 
@@ -3729,7 +3816,7 @@ class Team:
3729
3816
 
3730
3817
  try:
3731
3818
  sig = signature(value)
3732
- resolved_value = value(agent=self) if "agent" in sig.parameters else value()
3819
+ resolved_value = value(team=self) if "team" in sig.parameters else value()
3733
3820
 
3734
3821
  if iscoroutine(resolved_value):
3735
3822
  resolved_value = await resolved_value
@@ -4390,8 +4477,8 @@ class Team:
4390
4477
  f"<additional_context>\n{self.additional_context.strip()}\n</additional_context>\n\n"
4391
4478
  )
4392
4479
 
4393
- if self.add_session_state_to_context:
4394
- system_message_content += f"<session_state>\n{session_state}\n</session_state>\n\n"
4480
+ if self.add_session_state_to_context and session_state is not None:
4481
+ system_message_content += self._get_formatted_session_state_for_system_message(session_state)
4395
4482
 
4396
4483
  # Add the JSON output prompt if output_schema is provided and structured_outputs is False
4397
4484
  if (
@@ -4404,6 +4491,9 @@ class Team:
4404
4491
 
4405
4492
  return Message(role=self.system_message_role, content=system_message_content.strip())
4406
4493
 
4494
+ def _get_formatted_session_state_for_system_message(self, session_state: Dict[str, Any]) -> str:
4495
+ return f"\n<session_state>\n{session_state}\n</session_state>\n\n"
4496
+
4407
4497
  def _get_run_messages(
4408
4498
  self,
4409
4499
  *,
@@ -4595,7 +4685,13 @@ class Team:
4595
4685
  # If message is provided as a dict, try to validate it as a Message
4596
4686
  elif isinstance(input_message, dict):
4597
4687
  try:
4598
- return Message.model_validate(input_message)
4688
+ if self.input_schema and is_typed_dict(self.input_schema):
4689
+ import json
4690
+
4691
+ content = json.dumps(input_message, indent=2, ensure_ascii=False)
4692
+ return Message(role="user", content=content)
4693
+ else:
4694
+ return Message.model_validate(input_message)
4599
4695
  except Exception as e:
4600
4696
  log_warning(f"Failed to validate input: {e}")
4601
4697
 
@@ -5156,6 +5252,12 @@ class Team:
5156
5252
  if member_agent_run_response is not None:
5157
5253
  member_agent_run_response.parent_run_id = run_response.run_id # type: ignore
5158
5254
 
5255
+ # Update the top-level team run_response tool call to have the run_id of the member run
5256
+ if run_response.tools is not None:
5257
+ for tool in run_response.tools:
5258
+ if tool.tool_name and tool.tool_name.lower() == "delegate_task_to_member":
5259
+ tool.child_run_id = member_agent_run_response.run_id # type: ignore
5260
+
5159
5261
  # Update the team run context
5160
5262
  member_name = member_agent.name if member_agent.name else member_agent.id if member_agent.id else "Unknown"
5161
5263
  if isinstance(member_agent_task, str):
@@ -6040,7 +6142,8 @@ class Team:
6040
6142
  session = self.get_session(session_id=session_id) # type: ignore
6041
6143
 
6042
6144
  if session is None:
6043
- raise Exception("Session not found")
6145
+ log_warning(f"Session {session_id} not found")
6146
+ return []
6044
6147
 
6045
6148
  # Only filter by agent_id if this is part of a team
6046
6149
  return session.get_messages_from_last_n_runs(
agno/tools/mcp.py CHANGED
@@ -51,6 +51,7 @@ def _prepare_command(command: str) -> list[str]:
51
51
  "deno",
52
52
  "java",
53
53
  "ruby",
54
+ "docker",
54
55
  }
55
56
 
56
57
  executable = parts[0].split("/")[-1]
agno/tools/mem0.py CHANGED
@@ -2,7 +2,6 @@ import json
2
2
  from os import getenv
3
3
  from typing import Any, Dict, List, Optional, Union
4
4
 
5
- from agno.agent import Agent
6
5
  from agno.tools import Toolkit
7
6
  from agno.utils.log import log_debug, log_error, log_warning
8
7
 
@@ -69,15 +68,13 @@ class Mem0Tools(Toolkit):
69
68
  def _get_user_id(
70
69
  self,
71
70
  method_name: str,
72
- agent: Optional[Agent] = None,
71
+ session_state: Dict[str, Any],
73
72
  ) -> str:
74
73
  """Resolve the user ID"""
75
74
  resolved_user_id = self.user_id
76
- if not resolved_user_id and agent is not None:
75
+ if not resolved_user_id:
77
76
  try:
78
- session_state = getattr(agent, "session_state", None)
79
- if isinstance(session_state, dict):
80
- resolved_user_id = session_state.get("current_user_id")
77
+ resolved_user_id = session_state.get("current_user_id")
81
78
  except Exception:
82
79
  pass
83
80
  if not resolved_user_id:
@@ -88,7 +85,7 @@ class Mem0Tools(Toolkit):
88
85
 
89
86
  def add_memory(
90
87
  self,
91
- agent: Agent,
88
+ session_state,
92
89
  content: Union[str, Dict[str, str]],
93
90
  ) -> str:
94
91
  """Add facts to the user's memory.
@@ -101,7 +98,7 @@ class Mem0Tools(Toolkit):
101
98
  str: JSON-encoded Mem0 response or an error message.
102
99
  """
103
100
 
104
- resolved_user_id = self._get_user_id("add_memory", agent=agent)
101
+ resolved_user_id = self._get_user_id("add_memory", session_state=session_state)
105
102
  if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in add_memory:"):
106
103
  return resolved_user_id
107
104
  try:
@@ -116,7 +113,6 @@ class Mem0Tools(Toolkit):
116
113
  messages_list,
117
114
  user_id=resolved_user_id,
118
115
  infer=self.infer,
119
- output_format="v1.1",
120
116
  )
121
117
  return json.dumps(result)
122
118
  except Exception as e:
@@ -125,19 +121,18 @@ class Mem0Tools(Toolkit):
125
121
 
126
122
  def search_memory(
127
123
  self,
128
- agent: Agent,
124
+ session_state: Dict[str, Any],
129
125
  query: str,
130
126
  ) -> str:
131
127
  """Semantic search for *query* across the user's stored memories."""
132
128
 
133
- resolved_user_id = self._get_user_id("search_memory", agent=agent)
129
+ resolved_user_id = self._get_user_id("search_memory", session_state=session_state)
134
130
  if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in search_memory:"):
135
131
  return resolved_user_id
136
132
  try:
137
133
  results = self.client.search(
138
134
  query=query,
139
135
  user_id=resolved_user_id,
140
- output_format="v1.1",
141
136
  )
142
137
 
143
138
  if isinstance(results, dict) and "results" in results:
@@ -156,16 +151,15 @@ class Mem0Tools(Toolkit):
156
151
  log_error(f"Error searching memory: {e}")
157
152
  return f"Error searching memory: {e}"
158
153
 
159
- def get_all_memories(self, agent: Agent) -> str:
154
+ def get_all_memories(self, session_state: Dict[str, Any]) -> str:
160
155
  """Return **all** memories for the current user as a JSON string."""
161
156
 
162
- resolved_user_id = self._get_user_id("get_all_memories", agent=agent)
157
+ resolved_user_id = self._get_user_id("get_all_memories", session_state=session_state)
163
158
  if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in get_all_memories:"):
164
159
  return resolved_user_id
165
160
  try:
166
161
  results = self.client.get_all(
167
162
  user_id=resolved_user_id,
168
- output_format="v1.1",
169
163
  )
170
164
 
171
165
  if isinstance(results, dict) and "results" in results:
@@ -183,10 +177,10 @@ class Mem0Tools(Toolkit):
183
177
  log_error(f"Error getting all memories: {e}")
184
178
  return f"Error getting all memories: {e}"
185
179
 
186
- def delete_all_memories(self, agent: Agent) -> str:
180
+ def delete_all_memories(self, session_state: Dict[str, Any]) -> str:
187
181
  """Delete *all* memories associated with the current user"""
188
182
 
189
- resolved_user_id = self._get_user_id("delete_all_memories", agent=agent)
183
+ resolved_user_id = self._get_user_id("delete_all_memories", session_state=session_state)
190
184
  if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in delete_all_memories:"):
191
185
  error_msg = resolved_user_id
192
186
  log_error(error_msg)