agno 2.2.13__py3-none-any.whl → 2.3.1__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 (92) hide show
  1. agno/agent/agent.py +197 -110
  2. agno/api/api.py +2 -0
  3. agno/db/base.py +26 -0
  4. agno/db/dynamo/dynamo.py +8 -0
  5. agno/db/dynamo/schemas.py +1 -0
  6. agno/db/firestore/firestore.py +8 -0
  7. agno/db/firestore/schemas.py +1 -0
  8. agno/db/gcs_json/gcs_json_db.py +8 -0
  9. agno/db/in_memory/in_memory_db.py +8 -1
  10. agno/db/json/json_db.py +8 -0
  11. agno/db/migrations/manager.py +199 -0
  12. agno/db/migrations/versions/__init__.py +0 -0
  13. agno/db/migrations/versions/v2_3_0.py +938 -0
  14. agno/db/mongo/async_mongo.py +16 -6
  15. agno/db/mongo/mongo.py +11 -0
  16. agno/db/mongo/schemas.py +3 -0
  17. agno/db/mongo/utils.py +17 -0
  18. agno/db/mysql/mysql.py +76 -3
  19. agno/db/mysql/schemas.py +20 -10
  20. agno/db/postgres/async_postgres.py +99 -25
  21. agno/db/postgres/postgres.py +75 -6
  22. agno/db/postgres/schemas.py +30 -20
  23. agno/db/redis/redis.py +15 -2
  24. agno/db/redis/schemas.py +4 -0
  25. agno/db/schemas/memory.py +13 -0
  26. agno/db/singlestore/schemas.py +11 -0
  27. agno/db/singlestore/singlestore.py +79 -5
  28. agno/db/sqlite/async_sqlite.py +97 -19
  29. agno/db/sqlite/schemas.py +10 -0
  30. agno/db/sqlite/sqlite.py +79 -2
  31. agno/db/surrealdb/surrealdb.py +8 -0
  32. agno/knowledge/chunking/semantic.py +7 -2
  33. agno/knowledge/embedder/nebius.py +1 -1
  34. agno/knowledge/knowledge.py +57 -86
  35. agno/knowledge/reader/csv_reader.py +7 -9
  36. agno/knowledge/reader/docx_reader.py +5 -5
  37. agno/knowledge/reader/field_labeled_csv_reader.py +16 -18
  38. agno/knowledge/reader/json_reader.py +5 -4
  39. agno/knowledge/reader/markdown_reader.py +8 -8
  40. agno/knowledge/reader/pdf_reader.py +11 -11
  41. agno/knowledge/reader/pptx_reader.py +5 -5
  42. agno/knowledge/reader/s3_reader.py +3 -3
  43. agno/knowledge/reader/text_reader.py +8 -8
  44. agno/knowledge/reader/web_search_reader.py +1 -48
  45. agno/knowledge/reader/website_reader.py +10 -10
  46. agno/models/anthropic/claude.py +319 -28
  47. agno/models/aws/claude.py +32 -0
  48. agno/models/azure/openai_chat.py +19 -10
  49. agno/models/base.py +612 -545
  50. agno/models/cerebras/cerebras.py +8 -11
  51. agno/models/cohere/chat.py +27 -1
  52. agno/models/google/gemini.py +39 -7
  53. agno/models/groq/groq.py +25 -11
  54. agno/models/meta/llama.py +20 -9
  55. agno/models/meta/llama_openai.py +3 -19
  56. agno/models/nebius/nebius.py +4 -4
  57. agno/models/openai/chat.py +30 -14
  58. agno/models/openai/responses.py +10 -13
  59. agno/models/response.py +1 -0
  60. agno/models/vertexai/claude.py +26 -0
  61. agno/os/app.py +8 -19
  62. agno/os/router.py +54 -0
  63. agno/os/routers/knowledge/knowledge.py +2 -2
  64. agno/os/schema.py +2 -2
  65. agno/session/agent.py +57 -92
  66. agno/session/summary.py +1 -1
  67. agno/session/team.py +62 -112
  68. agno/session/workflow.py +353 -57
  69. agno/team/team.py +227 -125
  70. agno/tools/models/nebius.py +5 -5
  71. agno/tools/models_labs.py +20 -10
  72. agno/tools/nano_banana.py +151 -0
  73. agno/tools/yfinance.py +12 -11
  74. agno/utils/http.py +111 -0
  75. agno/utils/media.py +11 -0
  76. agno/utils/models/claude.py +8 -0
  77. agno/utils/print_response/agent.py +33 -12
  78. agno/utils/print_response/team.py +22 -12
  79. agno/vectordb/couchbase/couchbase.py +6 -2
  80. agno/workflow/condition.py +13 -0
  81. agno/workflow/loop.py +13 -0
  82. agno/workflow/parallel.py +13 -0
  83. agno/workflow/router.py +13 -0
  84. agno/workflow/step.py +120 -20
  85. agno/workflow/steps.py +13 -0
  86. agno/workflow/workflow.py +76 -63
  87. {agno-2.2.13.dist-info → agno-2.3.1.dist-info}/METADATA +6 -2
  88. {agno-2.2.13.dist-info → agno-2.3.1.dist-info}/RECORD +91 -88
  89. agno/tools/googlesearch.py +0 -98
  90. {agno-2.2.13.dist-info → agno-2.3.1.dist-info}/WHEEL +0 -0
  91. {agno-2.2.13.dist-info → agno-2.3.1.dist-info}/licenses/LICENSE +0 -0
  92. {agno-2.2.13.dist-info → agno-2.3.1.dist-info}/top_level.txt +0 -0
agno/team/team.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import contextlib
3
3
  import json
4
+ import warnings
4
5
  from collections import ChainMap, deque
5
6
  from copy import copy
6
7
  from dataclasses import dataclass
@@ -65,7 +66,6 @@ from agno.session.summary import SessionSummary
65
66
  from agno.tools import Toolkit
66
67
  from agno.tools.function import Function
67
68
  from agno.utils.agent import (
68
- aget_chat_history_util,
69
69
  aget_last_run_output_util,
70
70
  aget_run_output_util,
71
71
  aget_session_metrics_util,
@@ -79,7 +79,6 @@ from agno.utils.agent import (
79
79
  collect_joint_files,
80
80
  collect_joint_images,
81
81
  collect_joint_videos,
82
- get_chat_history_util,
83
82
  get_last_run_output_util,
84
83
  get_run_output_util,
85
84
  get_session_metrics_util,
@@ -194,10 +193,10 @@ class Team:
194
193
 
195
194
  # --- Team execution settings ---
196
195
  # If True, the team leader won't process responses from the members and instead will return them directly
197
- # Should not be used in combination with delegate_task_to_all_members
196
+ # Should not be used in combination with delegate_to_all_members
198
197
  respond_directly: bool = False
199
198
  # If True, the team leader will delegate the task to all members, instead of deciding for a subset
200
- delegate_task_to_all_members: bool = False
199
+ delegate_to_all_members: bool = False
201
200
  # Set to false if you want to send the run input directly to the member agents
202
201
  determine_input_for_members: bool = True
203
202
 
@@ -231,8 +230,6 @@ class Team:
231
230
  # Number of past sessions to include in the search
232
231
  num_history_sessions: Optional[int] = None
233
232
 
234
- # If True, adds a tool to allow the team to read the team history (this is deprecated and will be removed in a future version)
235
- read_team_history: bool = False
236
233
  # If True, adds a tool to allow the team to read the chat history
237
234
  read_chat_history: bool = False
238
235
 
@@ -257,7 +254,7 @@ class Team:
257
254
  # If True, add the team name to the instructions
258
255
  add_name_to_context: bool = False
259
256
  # If True, add the tools available to team members to the context
260
- add_member_tools_to_context: bool = True
257
+ add_member_tools_to_context: bool = False
261
258
 
262
259
  # Provide the system message as a string or function
263
260
  system_message: Optional[Union[str, Callable, Message]] = None
@@ -437,6 +434,9 @@ class Team:
437
434
  # This helps us improve the Teams implementation and provide better support
438
435
  telemetry: bool = True
439
436
 
437
+ # Deprecated. Use delegate_to_all_members instead.
438
+ delegate_task_to_all_members: bool = False
439
+
440
440
  def __init__(
441
441
  self,
442
442
  members: List[Union[Agent, "Team"]],
@@ -447,6 +447,7 @@ class Team:
447
447
  respond_directly: bool = False,
448
448
  determine_input_for_members: bool = True,
449
449
  delegate_task_to_all_members: bool = False,
450
+ delegate_to_all_members: bool = False,
450
451
  user_id: Optional[str] = None,
451
452
  session_id: Optional[str] = None,
452
453
  session_state: Optional[Dict[str, Any]] = None,
@@ -468,7 +469,7 @@ class Team:
468
469
  add_location_to_context: bool = False,
469
470
  timezone_identifier: Optional[str] = None,
470
471
  add_name_to_context: bool = False,
471
- add_member_tools_to_context: bool = True,
472
+ add_member_tools_to_context: bool = False,
472
473
  system_message: Optional[Union[str, Callable, Message]] = None,
473
474
  system_message_role: str = "system",
474
475
  additional_input: Optional[List[Union[str, Dict, BaseModel, Message]]] = None,
@@ -484,7 +485,6 @@ class Team:
484
485
  share_member_interactions: bool = False,
485
486
  get_member_information_tool: bool = False,
486
487
  search_knowledge: bool = True,
487
- read_team_history: bool = False,
488
488
  read_chat_history: bool = False,
489
489
  store_media: bool = True,
490
490
  store_tool_messages: bool = True,
@@ -537,6 +537,13 @@ class Team:
537
537
  exponential_backoff: bool = False,
538
538
  telemetry: bool = True,
539
539
  ):
540
+ if delegate_task_to_all_members:
541
+ warnings.warn(
542
+ "The 'delegate_task_to_all_members' parameter is deprecated and will be removed in future versions. Use 'delegate_to_all_members' instead.",
543
+ DeprecationWarning,
544
+ stacklevel=2,
545
+ )
546
+
540
547
  self.members = members
541
548
 
542
549
  self.model = model # type: ignore[assignment]
@@ -547,7 +554,7 @@ class Team:
547
554
 
548
555
  self.respond_directly = respond_directly
549
556
  self.determine_input_for_members = determine_input_for_members
550
- self.delegate_task_to_all_members = delegate_task_to_all_members
557
+ self.delegate_to_all_members = delegate_to_all_members or delegate_task_to_all_members
551
558
 
552
559
  self.user_id = user_id
553
560
  self.session_id = session_id
@@ -604,7 +611,7 @@ class Team:
604
611
  self.share_member_interactions = share_member_interactions
605
612
  self.get_member_information_tool = get_member_information_tool
606
613
  self.search_knowledge = search_knowledge
607
- self.read_chat_history = read_chat_history or read_team_history
614
+ self.read_chat_history = read_chat_history
608
615
 
609
616
  self.store_media = store_media
610
617
  self.store_tool_messages = store_tool_messages
@@ -920,9 +927,9 @@ class Team:
920
927
  # Make sure for the team, we are using the team logger
921
928
  use_team_logger()
922
929
 
923
- if self.delegate_task_to_all_members and self.respond_directly:
930
+ if self.delegate_to_all_members and self.respond_directly:
924
931
  log_warning(
925
- "`delegate_task_to_all_members` and `respond_directly` are both enabled. The task will be delegated to all members, but `respond_directly` will be disabled."
932
+ "`delegate_to_all_members` and `respond_directly` are both enabled. The task will be delegated to all members, but `respond_directly` will be disabled."
926
933
  )
927
934
  self.respond_directly = False
928
935
 
@@ -1821,6 +1828,13 @@ class Team:
1821
1828
  "add_history_to_context is True, but no database has been assigned to the team. History will not be added to the context."
1822
1829
  )
1823
1830
 
1831
+ if yield_run_response is not None:
1832
+ warnings.warn(
1833
+ "The 'yield_run_response' parameter is deprecated and will be removed in future versions. Use 'yield_run_output' instead.",
1834
+ DeprecationWarning,
1835
+ stacklevel=2,
1836
+ )
1837
+
1824
1838
  # Create a run_id for this specific run
1825
1839
  run_id = str(uuid4())
1826
1840
 
@@ -2262,6 +2276,7 @@ class Team:
2262
2276
  await memory_task
2263
2277
  except asyncio.CancelledError:
2264
2278
  pass
2279
+
2265
2280
  # Always clean up the run tracking
2266
2281
  cleanup_run(run_response.run_id) # type: ignore
2267
2282
 
@@ -2583,6 +2598,7 @@ class Team:
2583
2598
  await memory_task
2584
2599
  except asyncio.CancelledError:
2585
2600
  pass
2601
+
2586
2602
  # Always clean up the run tracking
2587
2603
  cleanup_run(run_response.run_id) # type: ignore
2588
2604
 
@@ -2676,6 +2692,13 @@ class Team:
2676
2692
  "add_history_to_context is True, but no database has been assigned to the team. History will not be added to the context."
2677
2693
  )
2678
2694
 
2695
+ if yield_run_response is not None:
2696
+ warnings.warn(
2697
+ "The 'yield_run_response' parameter is deprecated and will be removed in future versions. Use 'yield_run_output' instead.",
2698
+ DeprecationWarning,
2699
+ stacklevel=2,
2700
+ )
2701
+
2679
2702
  # Create a run_id for this specific run
2680
2703
  run_id = str(uuid4())
2681
2704
 
@@ -2725,6 +2748,12 @@ class Team:
2725
2748
  stream = False if self.stream is None else self.stream
2726
2749
 
2727
2750
  # Considering both stream_events and stream_intermediate_steps (deprecated)
2751
+ if stream_intermediate_steps is not None:
2752
+ warnings.warn(
2753
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
2754
+ DeprecationWarning,
2755
+ stacklevel=2,
2756
+ )
2728
2757
  stream_events = stream_events or stream_intermediate_steps
2729
2758
 
2730
2759
  # Can't stream events if streaming is disabled
@@ -3863,8 +3892,6 @@ class Team:
3863
3892
  input: Union[List, Dict, str, Message, BaseModel, List[Message]],
3864
3893
  *,
3865
3894
  stream: Optional[bool] = None,
3866
- stream_events: Optional[bool] = None,
3867
- stream_intermediate_steps: Optional[bool] = None,
3868
3895
  session_id: Optional[str] = None,
3869
3896
  session_state: Optional[Dict[str, Any]] = None,
3870
3897
  user_id: Optional[str] = None,
@@ -3879,14 +3906,31 @@ class Team:
3879
3906
  add_session_state_to_context: Optional[bool] = None,
3880
3907
  dependencies: Optional[Dict[str, Any]] = None,
3881
3908
  metadata: Optional[Dict[str, Any]] = None,
3909
+ stream_events: Optional[bool] = None,
3910
+ stream_intermediate_steps: Optional[bool] = None,
3882
3911
  debug_mode: Optional[bool] = None,
3883
3912
  show_message: bool = True,
3884
3913
  show_reasoning: bool = True,
3885
3914
  show_full_reasoning: bool = False,
3915
+ show_member_responses: Optional[bool] = None,
3886
3916
  console: Optional[Any] = None,
3887
3917
  tags_to_include_in_markdown: Optional[Set[str]] = None,
3888
3918
  **kwargs: Any,
3889
3919
  ) -> None:
3920
+ if stream_events is not None:
3921
+ warnings.warn(
3922
+ "The 'stream_events' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the print_response function.",
3923
+ DeprecationWarning,
3924
+ stacklevel=2,
3925
+ )
3926
+
3927
+ if stream_intermediate_steps is not None:
3928
+ warnings.warn(
3929
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the print_response function.",
3930
+ DeprecationWarning,
3931
+ stacklevel=2,
3932
+ )
3933
+
3890
3934
  if self._has_async_db():
3891
3935
  raise Exception(
3892
3936
  "This method is not supported with an async DB. Please use the async version of this method."
@@ -3904,15 +3948,11 @@ class Team:
3904
3948
  if stream is None:
3905
3949
  stream = self.stream or False
3906
3950
 
3907
- # Considering both stream_events and stream_intermediate_steps (deprecated)
3908
- stream_events = stream_events or stream_intermediate_steps
3951
+ if "stream_events" in kwargs:
3952
+ kwargs.pop("stream_events")
3909
3953
 
3910
- # Can't stream events if streaming is disabled
3911
- if stream is False:
3912
- stream_events = False
3913
-
3914
- if stream_events is None:
3915
- stream_events = False if self.stream_events is None else self.stream_events
3954
+ if show_member_responses is None:
3955
+ show_member_responses = self.show_members_responses
3916
3956
 
3917
3957
  if stream:
3918
3958
  print_response_stream(
@@ -3922,6 +3962,7 @@ class Team:
3922
3962
  show_message=show_message,
3923
3963
  show_reasoning=show_reasoning,
3924
3964
  show_full_reasoning=show_full_reasoning,
3965
+ show_member_responses=show_member_responses,
3925
3966
  tags_to_include_in_markdown=tags_to_include_in_markdown,
3926
3967
  session_id=session_id,
3927
3968
  session_state=session_state,
@@ -3931,7 +3972,7 @@ class Team:
3931
3972
  videos=videos,
3932
3973
  files=files,
3933
3974
  markdown=markdown,
3934
- stream_events=stream_events,
3975
+ stream_events=True,
3935
3976
  knowledge_filters=knowledge_filters,
3936
3977
  add_history_to_context=add_history_to_context,
3937
3978
  dependencies=dependencies,
@@ -3949,6 +3990,7 @@ class Team:
3949
3990
  show_message=show_message,
3950
3991
  show_reasoning=show_reasoning,
3951
3992
  show_full_reasoning=show_full_reasoning,
3993
+ show_member_responses=show_member_responses,
3952
3994
  tags_to_include_in_markdown=tags_to_include_in_markdown,
3953
3995
  session_id=session_id,
3954
3996
  session_state=session_state,
@@ -3973,8 +4015,6 @@ class Team:
3973
4015
  input: Union[List, Dict, str, Message, BaseModel, List[Message]],
3974
4016
  *,
3975
4017
  stream: Optional[bool] = None,
3976
- stream_events: Optional[bool] = None,
3977
- stream_intermediate_steps: Optional[bool] = None,
3978
4018
  session_id: Optional[str] = None,
3979
4019
  session_state: Optional[Dict[str, Any]] = None,
3980
4020
  user_id: Optional[str] = None,
@@ -3989,14 +4029,31 @@ class Team:
3989
4029
  add_dependencies_to_context: Optional[bool] = None,
3990
4030
  add_session_state_to_context: Optional[bool] = None,
3991
4031
  metadata: Optional[Dict[str, Any]] = None,
4032
+ stream_events: Optional[bool] = None,
4033
+ stream_intermediate_steps: Optional[bool] = None,
3992
4034
  debug_mode: Optional[bool] = None,
3993
4035
  show_message: bool = True,
3994
4036
  show_reasoning: bool = True,
3995
4037
  show_full_reasoning: bool = False,
4038
+ show_member_responses: Optional[bool] = None,
3996
4039
  console: Optional[Any] = None,
3997
4040
  tags_to_include_in_markdown: Optional[Set[str]] = None,
3998
4041
  **kwargs: Any,
3999
4042
  ) -> None:
4043
+ if stream_events is not None:
4044
+ warnings.warn(
4045
+ "The 'stream_events' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the aprint_response function.",
4046
+ DeprecationWarning,
4047
+ stacklevel=2,
4048
+ )
4049
+
4050
+ if stream_intermediate_steps is not None:
4051
+ warnings.warn(
4052
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the aprint_response function.",
4053
+ DeprecationWarning,
4054
+ stacklevel=2,
4055
+ )
4056
+
4000
4057
  if not tags_to_include_in_markdown:
4001
4058
  tags_to_include_in_markdown = {"think", "thinking"}
4002
4059
 
@@ -4009,15 +4066,11 @@ class Team:
4009
4066
  if stream is None:
4010
4067
  stream = self.stream or False
4011
4068
 
4012
- # Considering both stream_events and stream_intermediate_steps (deprecated)
4013
- stream_events = stream_events or stream_intermediate_steps
4069
+ if "stream_events" in kwargs:
4070
+ kwargs.pop("stream_events")
4014
4071
 
4015
- # Can't stream events if streaming is disabled
4016
- if stream is False:
4017
- stream_events = False
4018
-
4019
- if stream_events is None:
4020
- stream_events = False if self.stream_events is None else self.stream_events
4072
+ if show_member_responses is None:
4073
+ show_member_responses = self.show_members_responses
4021
4074
 
4022
4075
  if stream:
4023
4076
  await aprint_response_stream(
@@ -4027,6 +4080,7 @@ class Team:
4027
4080
  show_message=show_message,
4028
4081
  show_reasoning=show_reasoning,
4029
4082
  show_full_reasoning=show_full_reasoning,
4083
+ show_member_responses=show_member_responses,
4030
4084
  tags_to_include_in_markdown=tags_to_include_in_markdown,
4031
4085
  session_id=session_id,
4032
4086
  session_state=session_state,
@@ -4036,7 +4090,7 @@ class Team:
4036
4090
  videos=videos,
4037
4091
  files=files,
4038
4092
  markdown=markdown,
4039
- stream_events=stream_events,
4093
+ stream_events=True,
4040
4094
  knowledge_filters=knowledge_filters,
4041
4095
  add_history_to_context=add_history_to_context,
4042
4096
  dependencies=dependencies,
@@ -4054,6 +4108,7 @@ class Team:
4054
4108
  show_message=show_message,
4055
4109
  show_reasoning=show_reasoning,
4056
4110
  show_full_reasoning=show_full_reasoning,
4111
+ show_member_responses=show_member_responses,
4057
4112
  tags_to_include_in_markdown=tags_to_include_in_markdown,
4058
4113
  session_id=session_id,
4059
4114
  session_state=session_state,
@@ -5364,7 +5419,7 @@ class Team:
5364
5419
 
5365
5420
  system_message_content += "\n<how_to_respond>\n"
5366
5421
 
5367
- if self.delegate_task_to_all_members:
5422
+ if self.delegate_to_all_members:
5368
5423
  system_message_content += (
5369
5424
  "- You can either respond directly or use the `delegate_task_to_members` tool to delegate a task to all members in your team to get a collaborative response.\n"
5370
5425
  "- To delegate a task to all members in your team, call `delegate_task_to_members` ONLY once. This will delegate a task to all members in your team.\n"
@@ -5630,7 +5685,7 @@ class Team:
5630
5685
  additional_information.append(f"Your name is: {self.name}.")
5631
5686
 
5632
5687
  if self.knowledge is not None and self.enable_agentic_knowledge_filters:
5633
- valid_filters = await self.knowledge.aget_valid_filters()
5688
+ valid_filters = await self.knowledge.async_get_valid_filters()
5634
5689
  if valid_filters:
5635
5690
  valid_filters_str = ", ".join(valid_filters)
5636
5691
  additional_information.append(
@@ -5664,7 +5719,7 @@ class Team:
5664
5719
 
5665
5720
  system_message_content += "\n<how_to_respond>\n"
5666
5721
 
5667
- if self.delegate_task_to_all_members:
5722
+ if self.delegate_to_all_members:
5668
5723
  system_message_content += (
5669
5724
  "- Your role is to forward tasks to members in your team with the highest likelihood of completing the user's request.\n"
5670
5725
  "- You can either respond directly or use the `delegate_task_to_members` tool to delegate a task to all members in your team to get a collaborative response.\n"
@@ -5911,10 +5966,10 @@ class Team:
5911
5966
  self.system_message_role if self.system_message_role not in ["user", "assistant", "tool"] else None
5912
5967
  )
5913
5968
 
5914
- history = session.get_messages_from_last_n_runs(
5915
- last_n=self.num_history_runs,
5916
- last_n_messages=self.num_history_messages,
5917
- skip_role=skip_role,
5969
+ history = session.get_messages(
5970
+ last_n_runs=self.num_history_runs,
5971
+ limit=self.num_history_messages,
5972
+ skip_roles=[skip_role] if skip_role else None,
5918
5973
  team_id=self.id if self.parent_team_id is not None else None,
5919
5974
  )
5920
5975
 
@@ -6043,10 +6098,10 @@ class Team:
6043
6098
  skip_role = (
6044
6099
  self.system_message_role if self.system_message_role not in ["user", "assistant", "tool"] else None
6045
6100
  )
6046
- history = session.get_messages_from_last_n_runs(
6047
- last_n=self.num_history_runs,
6048
- last_n_messages=self.num_history_messages,
6049
- skip_role=skip_role,
6101
+ history = session.get_messages(
6102
+ last_n_runs=self.num_history_runs,
6103
+ limit=self.num_history_messages,
6104
+ skip_roles=[skip_role] if skip_role else None,
6050
6105
  team_id=self.id,
6051
6106
  )
6052
6107
 
@@ -6527,9 +6582,7 @@ class Team:
6527
6582
 
6528
6583
  history: List[Dict[str, Any]] = []
6529
6584
 
6530
- all_chats = session.get_messages_from_last_n_runs(
6531
- team_id=self.id,
6532
- )
6585
+ all_chats = session.get_messages(team_id=self.id)
6533
6586
 
6534
6587
  if len(all_chats) == 0:
6535
6588
  return ""
@@ -6563,9 +6616,7 @@ class Team:
6563
6616
 
6564
6617
  history: List[Dict[str, Any]] = []
6565
6618
 
6566
- all_chats = session.get_messages_from_last_n_runs(
6567
- team_id=self.id,
6568
- )
6619
+ all_chats = session.get_messages(team_id=self.id)
6569
6620
 
6570
6621
  if len(all_chats) == 0:
6571
6622
  return ""
@@ -6737,18 +6788,20 @@ class Team:
6737
6788
  member_agent_id = member_agent.id if isinstance(member_agent, Agent) else None
6738
6789
  member_team_id = member_agent.id if isinstance(member_agent, Team) else None
6739
6790
 
6791
+ if not member_agent_id and not member_team_id:
6792
+ return []
6793
+
6740
6794
  # Only skip messages from history when system_message_role is NOT a standard conversation role.
6741
6795
  # Standard conversation roles ("user", "assistant", "tool") should never be filtered
6742
6796
  # to preserve conversation continuity.
6743
6797
  skip_role = self.system_message_role if self.system_message_role not in ["user", "assistant", "tool"] else None
6744
6798
 
6745
- history = session.get_messages_from_last_n_runs(
6746
- last_n=member_agent.num_history_runs or self.num_history_runs,
6747
- last_n_messages=member_agent.num_history_messages,
6748
- skip_role=skip_role,
6749
- agent_id=member_agent_id,
6799
+ history = session.get_messages(
6800
+ last_n_runs=member_agent.num_history_runs or self.num_history_runs,
6801
+ limit=member_agent.num_history_messages,
6802
+ skip_roles=[skip_role] if skip_role else None,
6803
+ member_ids=[member_agent_id] if member_agent_id else None,
6750
6804
  team_id=member_team_id,
6751
- member_runs=True,
6752
6805
  )
6753
6806
 
6754
6807
  if len(history) > 0:
@@ -7003,12 +7056,10 @@ class Team:
7003
7056
  )
7004
7057
  member_agent_run_response = None
7005
7058
  for member_agent_run_output_event in member_agent_run_response_stream:
7006
- # If we get the final response, we can break out of the loop
7007
- if isinstance(member_agent_run_output_event, TeamRunOutput) or isinstance(
7008
- member_agent_run_output_event, RunOutput
7009
- ):
7059
+ # Do NOT break out of the loop, Iterator need to exit properly
7060
+ if isinstance(member_agent_run_output_event, (TeamRunOutput, RunOutput)):
7010
7061
  member_agent_run_response = member_agent_run_output_event # type: ignore
7011
- break
7062
+ continue # Don't yield TeamRunOutput or RunOutput, only yield events
7012
7063
 
7013
7064
  # Check if the run is cancelled
7014
7065
  check_if_run_cancelled(member_agent_run_output_event)
@@ -7017,7 +7068,7 @@ class Team:
7017
7068
  member_agent_run_output_event.parent_run_id = (
7018
7069
  member_agent_run_output_event.parent_run_id or run_response.run_id
7019
7070
  )
7020
- yield member_agent_run_output_event
7071
+ yield member_agent_run_output_event # type: ignore
7021
7072
  else:
7022
7073
  member_agent_run_response = member_agent.run( # type: ignore
7023
7074
  input=member_agent_task if not history else history, # type: ignore
@@ -7133,12 +7184,10 @@ class Team:
7133
7184
  )
7134
7185
  member_agent_run_response = None
7135
7186
  async for member_agent_run_response_event in member_agent_run_response_stream:
7136
- # If we get the final response, we can break out of the loop
7137
- if isinstance(member_agent_run_response_event, TeamRunOutput) or isinstance(
7138
- member_agent_run_response_event, RunOutput
7139
- ):
7187
+ # Do NOT break out of the loop, AsyncIterator need to exit properly
7188
+ if isinstance(member_agent_run_response_event, (TeamRunOutput, RunOutput)):
7140
7189
  member_agent_run_response = member_agent_run_response_event # type: ignore
7141
- break
7190
+ continue # Don't yield TeamRunOutput or RunOutput, only yield events
7142
7191
 
7143
7192
  # Check if the run is cancelled
7144
7193
  check_if_run_cancelled(member_agent_run_response_event)
@@ -7147,7 +7196,7 @@ class Team:
7147
7196
  member_agent_run_response_event.parent_run_id = (
7148
7197
  getattr(member_agent_run_response_event, "parent_run_id", None) or run_response.run_id
7149
7198
  )
7150
- yield member_agent_run_response_event
7199
+ yield member_agent_run_response_event # type: ignore
7151
7200
  else:
7152
7201
  member_agent_run_response = await member_agent.arun( # type: ignore
7153
7202
  input=member_agent_task if not history else history,
@@ -7249,12 +7298,10 @@ class Team:
7249
7298
  )
7250
7299
  member_agent_run_response = None
7251
7300
  for member_agent_run_response_chunk in member_agent_run_response_stream:
7252
- # If we get the final response, we can break out of the loop
7253
- if isinstance(member_agent_run_response_chunk, TeamRunOutput) or isinstance(
7254
- member_agent_run_response_chunk, RunOutput
7255
- ):
7301
+ # Do NOT break out of the loop, Iterator need to exit properly
7302
+ if isinstance(member_agent_run_response_chunk, (TeamRunOutput, RunOutput)):
7256
7303
  member_agent_run_response = member_agent_run_response_chunk # type: ignore
7257
- break
7304
+ continue # Don't yield TeamRunOutput or RunOutput, only yield events
7258
7305
 
7259
7306
  # Check if the run is cancelled
7260
7307
  check_if_run_cancelled(member_agent_run_response_chunk)
@@ -7263,7 +7310,7 @@ class Team:
7263
7310
  member_agent_run_response_chunk.parent_run_id = (
7264
7311
  member_agent_run_response_chunk.parent_run_id or run_response.run_id
7265
7312
  )
7266
- yield member_agent_run_response_chunk
7313
+ yield member_agent_run_response_chunk # type: ignore
7267
7314
 
7268
7315
  else:
7269
7316
  member_agent_run_response = member_agent.run( # type: ignore
@@ -7366,11 +7413,11 @@ class Team:
7366
7413
  member_agent_run_response = None
7367
7414
  try:
7368
7415
  async for member_agent_run_output_event in member_stream:
7369
- if isinstance(member_agent_run_output_event, TeamRunOutput) or isinstance(
7370
- member_agent_run_output_event, RunOutput
7371
- ):
7416
+ # Do NOT break out of the loop, AsyncIterator need to exit properly
7417
+ if isinstance(member_agent_run_output_event, (TeamRunOutput, RunOutput)):
7372
7418
  member_agent_run_response = member_agent_run_output_event # type: ignore
7373
- break
7419
+ continue # Don't yield TeamRunOutput or RunOutput, only yield events
7420
+
7374
7421
  check_if_run_cancelled(member_agent_run_output_event)
7375
7422
  member_agent_run_output_event.parent_run_id = (
7376
7423
  member_agent_run_output_event.parent_run_id or run_response.run_id
@@ -7486,7 +7533,7 @@ class Team:
7486
7533
  # After all the member runs, switch back to the team logger
7487
7534
  use_team_logger()
7488
7535
 
7489
- if self.delegate_task_to_all_members:
7536
+ if self.delegate_to_all_members:
7490
7537
  if async_mode:
7491
7538
  delegate_function = adelegate_task_to_members # type: ignore
7492
7539
  else:
@@ -7794,7 +7841,13 @@ class Team:
7794
7841
  loaded_session = cast(TeamSession, self._read_session(session_id=session_id_to_load)) # type: ignore
7795
7842
  # We have a workflow team, so we are loading a WorkflowSession
7796
7843
  else:
7797
- loaded_session = cast(WorkflowSession, self._read_session(session_id=session_id_to_load)) # type: ignore
7844
+ loaded_session = cast(
7845
+ WorkflowSession,
7846
+ self._read_session(
7847
+ session_id=session_id_to_load, # type: ignore
7848
+ session_type=SessionType.WORKFLOW,
7849
+ ),
7850
+ )
7798
7851
 
7799
7852
  # Cache the session if relevant
7800
7853
  if loaded_session is not None and self.cache_session:
@@ -7835,7 +7888,13 @@ class Team:
7835
7888
  loaded_session = cast(TeamSession, await self._aread_session(session_id=session_id_to_load)) # type: ignore
7836
7889
  # We have a workflow team, so we are loading a WorkflowSession
7837
7890
  else:
7838
- loaded_session = cast(WorkflowSession, await self._aread_session(session_id=session_id_to_load)) # type: ignore
7891
+ loaded_session = cast(
7892
+ WorkflowSession,
7893
+ await self._aread_session(
7894
+ session_id=session_id_to_load, # type: ignore
7895
+ session_type=SessionType.WORKFLOW,
7896
+ ),
7897
+ )
7839
7898
 
7840
7899
  # Cache the session if relevant
7841
7900
  if loaded_session is not None and self.cache_session:
@@ -7916,7 +7975,7 @@ class Team:
7916
7975
  gen_session_name_prompt = "Team Conversation\n"
7917
7976
 
7918
7977
  # Get team session messages for generating the name
7919
- messages_for_generating_session_name = self.get_messages_for_session()
7978
+ messages_for_generating_session_name = self.get_session_messages()
7920
7979
 
7921
7980
  for message in messages_for_generating_session_name:
7922
7981
  gen_session_name_prompt += f"{message.role.upper()}: {message.content}\n"
@@ -8117,39 +8176,29 @@ class Team:
8117
8176
  return
8118
8177
  await self.db.delete_session(session_id=session_id) # type: ignore
8119
8178
 
8120
- def get_chat_history(self, session_id: Optional[str] = None) -> List[Message]:
8121
- """Read the chat history from the session
8122
-
8123
- Args:
8124
- session_id: The session ID to get the chat history for. If not provided, the current cached session ID is used.
8125
- Returns:
8126
- List[Message]: The chat history from the session.
8127
- """
8128
- session_id = session_id or self.session_id
8129
- if session_id is None:
8130
- raise Exception("Session ID is not set")
8131
-
8132
- return get_chat_history_util(self, session_id=session_id)
8133
-
8134
- async def aget_chat_history(self, session_id: Optional[str] = None) -> List[Message]:
8135
- """Read the chat history from the session
8136
-
8137
- Args:
8138
- session_id: The session ID to get the chat history for. If not provided, the current cached session ID is used.
8139
- Returns:
8140
- List[Message]: The chat history from the session.
8141
- """
8142
- session_id = session_id or self.session_id
8143
- if session_id is None:
8144
- raise Exception("Session ID is not set")
8145
-
8146
- return await aget_chat_history_util(self, session_id=session_id)
8147
-
8148
- def get_messages_for_session(self, session_id: Optional[str] = None) -> List[Message]:
8149
- """Get messages for a session
8179
+ def get_session_messages(
8180
+ self,
8181
+ session_id: Optional[str] = None,
8182
+ member_ids: Optional[List[str]] = None,
8183
+ last_n_runs: Optional[int] = None,
8184
+ limit: Optional[int] = None,
8185
+ skip_roles: Optional[List[str]] = None,
8186
+ skip_statuses: Optional[List[RunStatus]] = None,
8187
+ skip_history_messages: bool = True,
8188
+ skip_member_messages: bool = True,
8189
+ ) -> List[Message]:
8190
+ """Get all messages belonging to the given session.
8150
8191
 
8151
8192
  Args:
8152
8193
  session_id: The session ID to get the messages for. If not provided, the current cached session ID is used.
8194
+ member_ids: The ids of the members to get the messages from.
8195
+ last_n_runs: The number of runs to return messages from, counting from the latest. Defaults to all runs.
8196
+ limit: The number of messages to return, counting from the latest. Defaults to all messages.
8197
+ skip_roles: Skip messages with these roles.
8198
+ skip_statuses: Skip messages with these statuses.
8199
+ skip_history_messages: Skip messages that were tagged as history in previous runs.
8200
+ skip_member_messages: Skip messages created by members of the team.
8201
+
8153
8202
  Returns:
8154
8203
  List[Message]: The messages for the session.
8155
8204
  """
@@ -8159,21 +8208,44 @@ class Team:
8159
8208
  return []
8160
8209
 
8161
8210
  session = self.get_session(session_id=session_id) # type: ignore
8162
-
8163
8211
  if session is None:
8164
8212
  log_warning(f"Session {session_id} not found")
8165
8213
  return []
8166
8214
 
8167
- # Only filter by agent_id if this is part of a team
8168
- return session.get_messages_from_last_n_runs(
8215
+ return session.get_messages(
8169
8216
  team_id=self.id,
8217
+ member_ids=member_ids,
8218
+ last_n_runs=last_n_runs,
8219
+ limit=limit,
8220
+ skip_roles=skip_roles,
8221
+ skip_statuses=skip_statuses,
8222
+ skip_history_messages=skip_history_messages,
8223
+ skip_member_messages=skip_member_messages,
8170
8224
  )
8171
8225
 
8172
- async def aget_messages_for_session(self, session_id: Optional[str] = None) -> List[Message]:
8173
- """Get messages for a session
8226
+ async def aget_session_messages(
8227
+ self,
8228
+ session_id: Optional[str] = None,
8229
+ member_ids: Optional[List[str]] = None,
8230
+ last_n_runs: Optional[int] = None,
8231
+ limit: Optional[int] = None,
8232
+ skip_roles: Optional[List[str]] = None,
8233
+ skip_statuses: Optional[List[RunStatus]] = None,
8234
+ skip_history_messages: bool = True,
8235
+ skip_member_messages: bool = True,
8236
+ ) -> List[Message]:
8237
+ """Get all messages belonging to the given session.
8174
8238
 
8175
8239
  Args:
8176
8240
  session_id: The session ID to get the messages for. If not provided, the current cached session ID is used.
8241
+ member_ids: The ids of the members to get the messages from.
8242
+ last_n_runs: The number of runs to return messages from, counting from the latest. Defaults to all runs.
8243
+ limit: The number of messages to return, counting from the latest. Defaults to all messages.
8244
+ skip_roles: Skip messages with these roles.
8245
+ skip_statuses: Skip messages with these statuses.
8246
+ skip_history_messages: Skip messages that were tagged as history in previous runs.
8247
+ skip_member_messages: Skip messages created by members of the team.
8248
+
8177
8249
  Returns:
8178
8250
  List[Message]: The messages for the session.
8179
8251
  """
@@ -8183,14 +8255,47 @@ class Team:
8183
8255
  return []
8184
8256
 
8185
8257
  session = await self.aget_session(session_id=session_id) # type: ignore
8186
-
8187
8258
  if session is None:
8188
8259
  log_warning(f"Session {session_id} not found")
8189
8260
  return []
8190
8261
 
8191
- # Only filter by agent_id if this is part of a team
8192
- return session.get_messages_from_last_n_runs(
8262
+ return session.get_messages(
8193
8263
  team_id=self.id,
8264
+ member_ids=member_ids,
8265
+ last_n_runs=last_n_runs,
8266
+ limit=limit,
8267
+ skip_roles=skip_roles,
8268
+ skip_statuses=skip_statuses,
8269
+ skip_history_messages=skip_history_messages,
8270
+ skip_member_messages=skip_member_messages,
8271
+ )
8272
+
8273
+ def get_chat_history(self, session_id: Optional[str] = None, last_n_runs: Optional[int] = None) -> List[Message]:
8274
+ """Return the chat history (user and assistant messages) for the session.
8275
+ Use get_messages() for more filtering options.
8276
+
8277
+ Args:
8278
+ session_id: The session ID to get the chat history for. If not provided, the current cached session ID is used.
8279
+
8280
+ Returns:
8281
+ List[Message]: The chat history from the session.
8282
+ """
8283
+ return self.get_session_messages(
8284
+ session_id=session_id, last_n_runs=last_n_runs, skip_roles=["system", "tool"], skip_member_messages=True
8285
+ )
8286
+
8287
+ async def aget_chat_history(
8288
+ self, session_id: Optional[str] = None, last_n_runs: Optional[int] = None
8289
+ ) -> List[Message]:
8290
+ """Read the chat history from the session
8291
+
8292
+ Args:
8293
+ session_id: The session ID to get the chat history for. If not provided, the current cached session ID is used.
8294
+ Returns:
8295
+ List[Message]: The chat history from the session.
8296
+ """
8297
+ return await self.aget_session_messages(
8298
+ session_id=session_id, last_n_runs=last_n_runs, skip_roles=["system", "tool"], skip_member_messages=True
8194
8299
  )
8195
8300
 
8196
8301
  def get_session_summary(self, session_id: Optional[str] = None) -> Optional[SessionSummary]:
@@ -8412,7 +8517,6 @@ class Team:
8412
8517
  if invalid_keys:
8413
8518
  # type: ignore
8414
8519
  log_warning(f"Invalid filter keys provided: {invalid_keys}. These filters will be ignored.")
8415
- log_info(f"Valid filter keys are: {self.knowledge.valid_metadata_filters}") # type: ignore
8416
8520
 
8417
8521
  # Only use valid filters
8418
8522
  filters = valid_filters
@@ -8480,8 +8584,6 @@ class Team:
8480
8584
  if invalid_keys:
8481
8585
  # type: ignore
8482
8586
  log_warning(f"Invalid filter keys provided: {invalid_keys}. These filters will be ignored.")
8483
- # type: ignore
8484
- log_info(f"Valid filter keys are: {self.knowledge.valid_metadata_filters}")
8485
8587
 
8486
8588
  # Only use valid filters
8487
8589
  filters = valid_filters