agno 2.1.5__py3-none-any.whl → 2.1.6__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.
@@ -0,0 +1,87 @@
1
+ import dataclasses
2
+ from typing import Any, Optional, Sequence, TypeVar, Union, cast
3
+
4
+ from surrealdb import BlockingHttpSurrealConnection, BlockingWsSurrealConnection, Surreal
5
+
6
+ from agno.utils.log import logger
7
+
8
+ RecordType = TypeVar("RecordType")
9
+
10
+
11
+ def build_client(
12
+ url: str, creds: dict[str, str], ns: str, db: str
13
+ ) -> Union[BlockingWsSurrealConnection, BlockingHttpSurrealConnection]:
14
+ client = Surreal(url=url)
15
+ client.signin(creds)
16
+ client.use(namespace=ns, database=db)
17
+ return client
18
+
19
+
20
+ def _query_aux(
21
+ client: Union[BlockingWsSurrealConnection, BlockingHttpSurrealConnection],
22
+ query: str,
23
+ vars: dict[str, Any],
24
+ ) -> Union[list, dict, str, int]:
25
+ try:
26
+ response = client.query(query, vars)
27
+ except Exception as e:
28
+ msg = f"!! Query execution error: {query} with {vars}, Error: {e}"
29
+ logger.error(msg)
30
+ raise RuntimeError(msg)
31
+ return response
32
+
33
+
34
+ def query(
35
+ client: Union[BlockingWsSurrealConnection, BlockingHttpSurrealConnection],
36
+ query: str,
37
+ vars: dict[str, Any],
38
+ record_type: type[RecordType],
39
+ ) -> Sequence[RecordType]:
40
+ response = _query_aux(client, query, vars)
41
+ if isinstance(response, list):
42
+ if dataclasses.is_dataclass(record_type) and hasattr(record_type, "from_dict"):
43
+ return [getattr(record_type, "from_dict").__call__(x) for x in response]
44
+ else:
45
+ result: list[RecordType] = []
46
+ for x in response:
47
+ if isinstance(x, dict):
48
+ result.append(record_type(**x))
49
+ else:
50
+ result.append(record_type.__call__(x))
51
+ return result
52
+ else:
53
+ raise ValueError(f"Unexpected response type: {type(response)}")
54
+
55
+
56
+ def query_one(
57
+ client: Union[BlockingWsSurrealConnection, BlockingHttpSurrealConnection],
58
+ query: str,
59
+ vars: dict[str, Any],
60
+ record_type: type[RecordType],
61
+ ) -> Optional[RecordType]:
62
+ response = _query_aux(client, query, vars)
63
+ if response is None:
64
+ return None
65
+ elif not isinstance(response, list):
66
+ if dataclasses.is_dataclass(record_type) and hasattr(record_type, "from_dict"):
67
+ return getattr(record_type, "from_dict").__call__(response)
68
+ elif isinstance(response, dict):
69
+ return record_type(**response)
70
+ else:
71
+ return record_type.__call__(response)
72
+ elif isinstance(response, list):
73
+ # Handle list responses - SurrealDB might return a list with a single element
74
+ if len(response) == 1 and isinstance(response[0], dict):
75
+ result = response[0]
76
+ if dataclasses.is_dataclass(record_type) and hasattr(record_type, "from_dict"):
77
+ return getattr(record_type, "from_dict").__call__(result)
78
+ elif record_type is dict:
79
+ return cast(RecordType, result)
80
+ else:
81
+ return record_type(**result)
82
+ elif len(response) == 0:
83
+ return None
84
+ else:
85
+ raise ValueError(f"Expected single record, got {len(response)} records: {response}")
86
+ else:
87
+ raise ValueError(f"Unexpected response type: {type(response)}")
agno/memory/manager.py CHANGED
@@ -36,7 +36,7 @@ class MemoryManager:
36
36
  system_message: Optional[str] = None
37
37
  # Provide the memory capture instructions for the manager as a string. If not provided, a default prompt will be used.
38
38
  memory_capture_instructions: Optional[str] = None
39
- # Additional instructions for the manager
39
+ # Additional instructions for the manager. These instructions are appended to the default system prompt.
40
40
  additional_instructions: Optional[str] = None
41
41
 
42
42
  # Whether memories were created in the last run
@@ -719,17 +719,17 @@ class MemoryManager:
719
719
  return Message(role="system", content=self.system_message)
720
720
 
721
721
  memory_capture_instructions = self.memory_capture_instructions or dedent("""\
722
- Memories should include details that could personalize ongoing interactions with the user, such as:
723
- - Personal facts: name, age, occupation, location, interests, preferences, etc.
724
- - Significant life events or experiences shared by the user
725
- - Important context about the user's current situation, challenges or goals
726
- - What the user likes or dislikes, their opinions, beliefs, values, etc.
727
- - Any other details that provide valuable insights into the user's personality, perspective or needs\
722
+ Memories should capture personal information about the user that is relevant to the current conversation, such as:
723
+ - Personal facts: name, age, occupation, location, interests, and preferences
724
+ - Opinions and preferences: what the user likes, dislikes, enjoys, or finds frustrating
725
+ - Significant life events or experiences shared by the user
726
+ - Important context about the user's current situation, challenges, or goals
727
+ - Any other details that offer meaningful insight into the user's personality, perspective, or needs
728
728
  """)
729
729
 
730
730
  # -*- Return a system message for the memory manager
731
731
  system_prompt_lines = [
732
- "You are a MemoryConnector that is responsible for manging key information about the user. "
732
+ "You are a Memory Manager that is responsible for managing information and preferences about the user. "
733
733
  "You will be provided with a criteria for memories to capture in the <memories_to_capture> section and a list of existing memories in the <existing_memories> section.",
734
734
  "",
735
735
  "## When to add or update memories",
@@ -758,16 +758,16 @@ class MemoryManager:
758
758
  "",
759
759
  "## Updating memories",
760
760
  "You will also be provided with a list of existing memories in the <existing_memories> section. You can:",
761
- " 1. Decide to make no changes.",
761
+ " - Decide to make no changes.",
762
762
  ]
763
763
  if enable_add_memory:
764
- system_prompt_lines.append(" 2. Decide to add a new memory, using the `add_memory` tool.")
764
+ system_prompt_lines.append(" - Decide to add a new memory, using the `add_memory` tool.")
765
765
  if enable_update_memory:
766
- system_prompt_lines.append(" 3. Decide to update an existing memory, using the `update_memory` tool.")
766
+ system_prompt_lines.append(" - Decide to update an existing memory, using the `update_memory` tool.")
767
767
  if enable_delete_memory:
768
- system_prompt_lines.append(" 4. Decide to delete an existing memory, using the `delete_memory` tool.")
768
+ system_prompt_lines.append(" - Decide to delete an existing memory, using the `delete_memory` tool.")
769
769
  if enable_clear_memory:
770
- system_prompt_lines.append(" 5. Decide to clear all memories, using the `clear_memory` tool.")
770
+ system_prompt_lines.append(" - Decide to clear all memories, using the `clear_memory` tool.")
771
771
 
772
772
  system_prompt_lines += [
773
773
  "You can call multiple tools in a single response if needed. ",
agno/os/utils.py CHANGED
@@ -2,15 +2,15 @@ from typing import Any, Callable, Dict, List, Optional, Set, Union
2
2
 
3
3
  from fastapi import FastAPI, HTTPException, UploadFile
4
4
  from fastapi.routing import APIRoute, APIRouter
5
- from starlette.middleware.cors import CORSMiddleware
6
5
  from pydantic import BaseModel
6
+ from starlette.middleware.cors import CORSMiddleware
7
7
 
8
- from agno.models.message import Message
9
8
  from agno.agent.agent import Agent
10
9
  from agno.db.base import AsyncBaseDb, BaseDb
11
10
  from agno.knowledge.knowledge import Knowledge
12
11
  from agno.media import Audio, Image, Video
13
12
  from agno.media import File as FileMedia
13
+ from agno.models.message import Message
14
14
  from agno.os.config import AgentOSConfig
15
15
  from agno.team.team import Team
16
16
  from agno.tools import Toolkit
@@ -57,7 +57,7 @@ def get_knowledge_instance_by_db_id(knowledge_instances: List[Knowledge], db_id:
57
57
 
58
58
  def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> str:
59
59
  """Get the run input from the given run dictionary
60
-
60
+
61
61
  Uses the RunInput/TeamRunInput object which stores the original user input.
62
62
  """
63
63
 
@@ -67,12 +67,12 @@ def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> st
67
67
  if isinstance(input_data, dict) and input_data.get("input_content") is not None:
68
68
  return stringify_input_content(input_data["input_content"])
69
69
 
70
- if is_workflow_run:
70
+ if is_workflow_run:
71
71
  # Check the input field directly
72
72
  if run_dict.get("input") is not None:
73
73
  input_value = run_dict.get("input")
74
74
  return str(input_value)
75
-
75
+
76
76
  # Check the step executor runs for fallback
77
77
  step_executor_runs = run_dict.get("step_executor_runs", [])
78
78
  if step_executor_runs:
@@ -150,8 +150,6 @@ def get_session_name(session: Dict[str, Any]) -> str:
150
150
  return ""
151
151
 
152
152
 
153
-
154
-
155
153
  def extract_input_media(run_dict: Dict[str, Any]) -> Dict[str, Any]:
156
154
  input_media: Dict[str, List[Any]] = {
157
155
  "images": [],
@@ -165,7 +163,7 @@ def extract_input_media(run_dict: Dict[str, Any]) -> Dict[str, Any]:
165
163
  input_media["videos"].extend(input.get("videos", []))
166
164
  input_media["audios"].extend(input.get("audios", []))
167
165
  input_media["files"].extend(input.get("files", []))
168
-
166
+
169
167
  return input_media
170
168
 
171
169
 
@@ -528,7 +526,7 @@ def collect_mcp_tools_from_workflow_step(step: Any, mcp_tools: List[Any]) -> Non
528
526
 
529
527
  def stringify_input_content(input_content: Union[str, Dict[str, Any], List[Any], BaseModel]) -> str:
530
528
  """Convert any given input_content into its string representation.
531
-
529
+
532
530
  This handles both serialized (dict) and live (object) input_content formats.
533
531
  """
534
532
  import json
@@ -549,4 +547,4 @@ def stringify_input_content(input_content: Union[str, Dict[str, Any], List[Any],
549
547
  return input_content[0].get("content", str(input_content))
550
548
  return str(input_content)
551
549
  else:
552
- return str(input_content)
550
+ return str(input_content)
agno/team/team.py CHANGED
@@ -260,7 +260,7 @@ class Team:
260
260
  # If True, store media in run output
261
261
  store_media: bool = True
262
262
  # If True, store tool results in run output
263
- store_tool_results: bool = True
263
+ store_tool_messages: bool = True
264
264
  # If True, store history messages in run output
265
265
  store_history_messages: bool = True
266
266
 
@@ -422,7 +422,7 @@ class Team:
422
422
  search_knowledge: bool = True,
423
423
  read_team_history: bool = False,
424
424
  store_media: bool = True,
425
- store_tool_results: bool = True,
425
+ store_tool_messages: bool = True,
426
426
  store_history_messages: bool = True,
427
427
  send_media_to_model: bool = True,
428
428
  tools: Optional[List[Union[Toolkit, Callable, Function, Dict]]] = None,
@@ -524,7 +524,7 @@ class Team:
524
524
  self.read_team_history = read_team_history
525
525
 
526
526
  self.store_media = store_media
527
- self.store_tool_results = store_tool_results
527
+ self.store_tool_messages = store_tool_messages
528
528
  self.store_history_messages = store_history_messages
529
529
  self.send_media_to_model = send_media_to_model
530
530
 
@@ -1758,11 +1758,9 @@ class Team:
1758
1758
 
1759
1759
  async def _arun(
1760
1760
  self,
1761
- input: Union[str, List, Dict, Message, BaseModel],
1762
1761
  run_response: TeamRunOutput,
1763
1762
  session_id: str,
1764
1763
  session_state: Optional[Dict[str, Any]] = None,
1765
- store_member_responses: Optional[bool] = None,
1766
1764
  user_id: Optional[str] = None,
1767
1765
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
1768
1766
  add_dependencies_to_context: Optional[bool] = None,
@@ -1811,9 +1809,6 @@ class Team:
1811
1809
  self._update_metadata(session=team_session)
1812
1810
  session_state = self._load_session_state(session=team_session, session_state=session_state) # type: ignore
1813
1811
 
1814
- if store_member_responses is None:
1815
- store_member_responses = False if self.store_member_responses is None else self.store_member_responses
1816
-
1817
1812
  run_input = cast(TeamRunInput, run_response.input)
1818
1813
 
1819
1814
  # 3. Execute pre-hooks after session is loaded but before processing starts
@@ -1863,7 +1858,7 @@ class Team:
1863
1858
  session=team_session, # type: ignore
1864
1859
  session_state=session_state,
1865
1860
  user_id=user_id,
1866
- input_message=input,
1861
+ input_message=run_input.input_content,
1867
1862
  audio=audio,
1868
1863
  images=images,
1869
1864
  videos=videos,
@@ -1968,7 +1963,6 @@ class Team:
1968
1963
 
1969
1964
  async def _arun_stream(
1970
1965
  self,
1971
- input: Union[str, List, Dict, Message, BaseModel],
1972
1966
  run_response: TeamRunOutput,
1973
1967
  session_id: str,
1974
1968
  session_state: Optional[Dict[str, Any]] = None,
@@ -2051,7 +2045,7 @@ class Team:
2051
2045
  user_id=user_id,
2052
2046
  async_mode=True,
2053
2047
  knowledge_filters=knowledge_filters,
2054
- input_message=input,
2048
+ input_message=run_input.input_content,
2055
2049
  images=images,
2056
2050
  videos=videos,
2057
2051
  audio=audio,
@@ -2068,7 +2062,7 @@ class Team:
2068
2062
  session=team_session, # type: ignore
2069
2063
  session_state=session_state,
2070
2064
  user_id=user_id,
2071
- input_message=input,
2065
+ input_message=run_input.input_content,
2072
2066
  audio=audio,
2073
2067
  images=images,
2074
2068
  videos=videos,
@@ -3648,8 +3642,6 @@ class Team:
3648
3642
  run_response.input.audios = []
3649
3643
  run_response.input.files = []
3650
3644
 
3651
- # 2. RunOutput artifact media are skipped since we don't store them when store_media=False
3652
-
3653
3645
  # 3. Scrub media from all messages
3654
3646
  if run_response.messages:
3655
3647
  for message in run_response.messages:
@@ -3680,20 +3672,36 @@ class Team:
3680
3672
 
3681
3673
  def _scrub_tool_results_from_run_output(self, run_response: TeamRunOutput) -> None:
3682
3674
  """
3683
- Remove all tool-related data from TeamRunOutput when store_tool_results=False.
3684
- This includes tool calls, tool results, and tool-related message fields.
3675
+ Remove all tool-related data from RunOutput when store_tool_messages=False.
3676
+ This removes both the tool call and its corresponding result to maintain API consistency.
3685
3677
  """
3686
- # Remove tool results (messages with role="tool")
3687
- if run_response.messages:
3688
- run_response.messages = [msg for msg in run_response.messages if msg.role != "tool"]
3689
- # Also scrub tool-related fields from remaining messages
3690
- for message in run_response.messages:
3691
- self._scrub_tool_data_from_message(message)
3678
+ if not run_response.messages:
3679
+ return
3680
+
3681
+ # Step 1: Collect all tool_call_ids from tool result messages
3682
+ tool_call_ids_to_remove = set()
3683
+ for message in run_response.messages:
3684
+ if message.role == "tool" and message.tool_call_id:
3685
+ tool_call_ids_to_remove.add(message.tool_call_id)
3686
+
3687
+ # Step 2: Remove tool result messages (role="tool")
3688
+ run_response.messages = [msg for msg in run_response.messages if msg.role != "tool"]
3689
+
3690
+ # Step 3: Remove assistant messages that made those tool calls
3691
+ filtered_messages = []
3692
+ for message in run_response.messages:
3693
+ # Check if this assistant message made any of the tool calls we're removing
3694
+ should_remove = False
3695
+ if message.role == "assistant" and message.tool_calls:
3696
+ for tool_call in message.tool_calls:
3697
+ if tool_call.get("id") in tool_call_ids_to_remove:
3698
+ should_remove = True
3699
+ break
3692
3700
 
3693
- def _scrub_tool_data_from_message(self, message: Message) -> None:
3694
- """Remove tool-related data from a Message object."""
3695
- message.tool_calls = None
3696
- message.tool_call_id = None
3701
+ if not should_remove:
3702
+ filtered_messages.append(message)
3703
+
3704
+ run_response.messages = filtered_messages
3697
3705
 
3698
3706
  def _scrub_history_messages_from_run_output(self, run_response: TeamRunOutput) -> None:
3699
3707
  """
@@ -3715,7 +3723,7 @@ class Team:
3715
3723
  self._scrub_media_from_run_output(run_response)
3716
3724
  scrubbed = True
3717
3725
 
3718
- if not self.store_tool_results:
3726
+ if not self.store_tool_messages:
3719
3727
  self._scrub_tool_results_from_run_output(run_response)
3720
3728
  scrubbed = True
3721
3729
 
@@ -3725,6 +3733,37 @@ class Team:
3725
3733
 
3726
3734
  return scrubbed
3727
3735
 
3736
+ def _scrub_member_responses(self, member_responses: List[Union[TeamRunOutput, RunOutput]]) -> None:
3737
+ """
3738
+ Scrub member responses based on each member's storage flags.
3739
+ This is called when saving the team session to ensure member data is scrubbed per member settings.
3740
+ Recursively handles nested team's member responses.
3741
+ """
3742
+ for member_response in member_responses:
3743
+ member_id = None
3744
+ if isinstance(member_response, RunOutput):
3745
+ member_id = member_response.agent_id
3746
+ elif isinstance(member_response, TeamRunOutput):
3747
+ member_id = member_response.team_id
3748
+
3749
+ if not member_id:
3750
+ log_info("Skipping member response with no ID")
3751
+ continue
3752
+
3753
+ member_result = self._find_member_by_id(member_id)
3754
+ if not member_result:
3755
+ log_debug(f"Could not find member with ID: {member_id}")
3756
+ continue
3757
+
3758
+ _, member = member_result
3759
+
3760
+ if not member.store_media or not member.store_tool_messages or not member.store_history_messages:
3761
+ member._scrub_run_output_for_storage(member_response) # type: ignore
3762
+
3763
+ # If this is a nested team, recursively scrub its member responses
3764
+ if isinstance(member_response, TeamRunOutput) and member_response.member_responses:
3765
+ member._scrub_member_responses(member_response.member_responses) # type: ignore
3766
+
3728
3767
  def _validate_media_object_id(
3729
3768
  self,
3730
3769
  images: Optional[Sequence[Image]] = None,
@@ -5105,9 +5144,7 @@ class Team:
5105
5144
  _memory_manager_not_set = True
5106
5145
  user_memories = self.memory_manager.get_user_memories(user_id=user_id) # type: ignore
5107
5146
  if user_memories and len(user_memories) > 0:
5108
- system_message_content += (
5109
- "You have access to memories from previous interactions with the user that you can use:\n\n"
5110
- )
5147
+ system_message_content += "You have access to user info and preferences from previous interactions that you can use to personalize your response:\n\n"
5111
5148
  system_message_content += "<memories_from_previous_interactions>"
5112
5149
  for _memory in user_memories: # type: ignore
5113
5150
  system_message_content += f"\n- {_memory.memory}"
@@ -5406,9 +5443,7 @@ class Team:
5406
5443
  user_memories = self.memory_manager.get_user_memories(user_id=user_id) # type: ignore
5407
5444
 
5408
5445
  if user_memories and len(user_memories) > 0:
5409
- system_message_content += (
5410
- "You have access to memories from previous interactions with the user that you can use:\n\n"
5411
- )
5446
+ system_message_content += "You have access to user info and preferences from previous interactions that you can use to personalize your response:\n\n"
5412
5447
  system_message_content += "<memories_from_previous_interactions>"
5413
5448
  for _memory in user_memories: # type: ignore
5414
5449
  system_message_content += f"\n- {_memory.memory}"
@@ -6563,8 +6598,16 @@ class Team:
6563
6598
  if run_response and member_agent_run_response:
6564
6599
  run_response.add_member_run(member_agent_run_response)
6565
6600
 
6566
- # Add the member run to the team session
6601
+ # Scrub the member run based on that member's storage flags before storing
6567
6602
  if member_agent_run_response:
6603
+ if (
6604
+ not member_agent.store_media
6605
+ or not member_agent.store_tool_messages
6606
+ or not member_agent.store_history_messages
6607
+ ):
6608
+ member_agent._scrub_run_output_for_storage(member_agent_run_response) # type: ignore
6609
+
6610
+ # Add the member run to the team session
6568
6611
  session.upsert_run(member_agent_run_response)
6569
6612
 
6570
6613
  # Update team session state
@@ -6956,7 +6999,7 @@ class Team:
6956
6999
  done_marker = object()
6957
7000
  queue: "asyncio.Queue[Union[RunOutputEvent, TeamRunOutputEvent, str, object]]" = asyncio.Queue()
6958
7001
 
6959
- async def stream_member(agent: Union[Agent, "Team"], idx: int) -> None:
7002
+ async def stream_member(agent: Union[Agent, "Team"]) -> None:
6960
7003
  member_agent_task, history = _setup_delegate_task_to_member(
6961
7004
  agent, task_description, expected_output
6962
7005
  )
@@ -7004,11 +7047,10 @@ class Team:
7004
7047
 
7005
7048
  # Initialize and launch all members
7006
7049
  tasks: List[asyncio.Task[None]] = []
7007
- for member_agent_index, member_agent in enumerate(self.members):
7050
+ for member_agent in self.members:
7008
7051
  current_agent = member_agent
7009
- current_index = member_agent_index
7010
7052
  self._initialize_member(current_agent)
7011
- tasks.append(asyncio.create_task(stream_member(current_agent, current_index)))
7053
+ tasks.append(asyncio.create_task(stream_member(current_agent)))
7012
7054
 
7013
7055
  # Drain queue until all members reported done
7014
7056
  completed = 0
@@ -7033,7 +7075,6 @@ class Team:
7033
7075
  tasks = []
7034
7076
  for member_agent_index, member_agent in enumerate(self.members):
7035
7077
  current_agent = member_agent
7036
- current_index = member_agent_index
7037
7078
  member_agent_task, history = _setup_delegate_task_to_member(
7038
7079
  current_agent, task_description, expected_output
7039
7080
  )
@@ -7343,11 +7384,16 @@ class Team:
7343
7384
  session.session_data["session_state"].pop("current_user_id", None) # type: ignore
7344
7385
  session.session_data["session_state"].pop("current_run_id", None) # type: ignore
7345
7386
 
7346
- # scrub the member responses if not storing them
7347
- if not self.store_member_responses and session.runs is not None:
7387
+ # scrub the member responses based on storage settings
7388
+ if session.runs is not None:
7348
7389
  for run in session.runs:
7349
7390
  if hasattr(run, "member_responses"):
7350
- run.member_responses = []
7391
+ if not self.store_member_responses:
7392
+ # Remove all member responses
7393
+ run.member_responses = []
7394
+ else:
7395
+ # Scrub individual member responses based on their storage flags
7396
+ self._scrub_member_responses(run.member_responses)
7351
7397
  self._upsert_session(session=session)
7352
7398
  log_debug(f"Created or updated TeamSession record: {session.session_id}")
7353
7399
 
@@ -114,7 +114,6 @@ class SurrealDb(VectorDb):
114
114
  """Initialize SurrealDB connection.
115
115
 
116
116
  Args:
117
- url: SurrealDB server URL (e.g. ws://localhost:8000/rpc)
118
117
  client: A blocking connection, either HTTP or WS
119
118
  async_client: An async connection, either HTTP or WS (default: None)
120
119
  collection: Collection name to store documents (default: documents)
agno/workflow/step.py CHANGED
@@ -1058,6 +1058,14 @@ class Step:
1058
1058
  executor_run_response.parent_run_id = workflow_run_response.run_id
1059
1059
  executor_run_response.workflow_step_id = self.step_id
1060
1060
 
1061
+ # Scrub the executor response based on the executor's storage flags before storing
1062
+ if (
1063
+ not self.active_executor.store_media
1064
+ or not self.active_executor.store_tool_messages
1065
+ or not self.active_executor.store_history_messages
1066
+ ): # type: ignore
1067
+ self.active_executor._scrub_run_output_for_storage(executor_run_response) # type: ignore
1068
+
1061
1069
  # Get the raw response from the step's active executor
1062
1070
  raw_response = executor_run_response
1063
1071
  if raw_response and isinstance(raw_response, (RunOutput, TeamRunOutput)):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 2.1.5
3
+ Version: 2.1.6
4
4
  Summary: Agno: a lightweight library for building Multi-Agent Systems
5
5
  Author-email: Ashpreet Bedi <ashpreet@agno.com>
6
6
  Project-URL: homepage, https://agno.com
@@ -4,7 +4,7 @@ agno/exceptions.py,sha256=7xqLur8sWHugnViIJz4PvPKSHljSiVKNAqaKQOJgZiU,4982
4
4
  agno/media.py,sha256=eTfYb_pwhX_PCIVPSrW4VYRqmoxKABEF1aZClrVvQ30,16500
5
5
  agno/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  agno/agent/__init__.py,sha256=s7S3FgsjZxuaabzi8L5n4aSH8IZAiZ7XaNNcySGR-EQ,1051
7
- agno/agent/agent.py,sha256=V6UeCaN5WBY4P7VPL-wDJZyabS07UZ0hiSws-DQfRkA,403495
7
+ agno/agent/agent.py,sha256=SWsIFkDNdNEHynJu5MepO2gqlJnh_yFDN1tn7DT-TgI,403708
8
8
  agno/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  agno/api/agent.py,sha256=fKlQ62E_C9Rjd7Zus3Gs3R1RG-IhzFV-ICpkb6SLqYc,932
10
10
  agno/api/api.py,sha256=Z7iWbrjheJcGLeeDYrtTCWiKTVqjH0uJI35UNWOtAXw,973
@@ -52,17 +52,17 @@ agno/db/json/__init__.py,sha256=zyPTmVF9S-OwXCL7FSkrDmunZ_Q14YZO3NYUv1Pa14Y,62
52
52
  agno/db/json/json_db.py,sha256=ep1edUGQA-pUGAGxROLECrspEycZxVxHOk-y7qRVcmE,47655
53
53
  agno/db/json/utils.py,sha256=__c14xMdyw1AlyV7-DAGDr8YicqhfCbSS5C8OkVN2So,6658
54
54
  agno/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- agno/db/migrations/v1_to_v2.py,sha256=LtRliKUyrLbPhCcWwRz909_if442B3Nah7zqDjEdOCk,24415
55
+ agno/db/migrations/v1_to_v2.py,sha256=gj8deaEWUxOr0qJyMfjOpV3LxEh-otOSOxDckeUq0qU,24938
56
56
  agno/db/mongo/__init__.py,sha256=EPa9QkGNVwnuej72LhZDCeASMXa-e0pR20jsgwa9BhY,63
57
- agno/db/mongo/mongo.py,sha256=3gn-9D57RaPINATl_aBX-WxDZ0VhTwk-WhhSWR7KLy8,68685
57
+ agno/db/mongo/mongo.py,sha256=PjUEFjiOI0HywlDxj8DF1jhsv9-hejjJoiclpwMGkWk,68548
58
58
  agno/db/mongo/schemas.py,sha256=MAhfwx7_zxKucnZpgq_YSZANaF5MqiZ6qDByhdIREk8,2054
59
- agno/db/mongo/utils.py,sha256=dmVo0HGIG7IPKdCjuRDcO0ZOtyXcNkP6S2G-XBFqzZE,6906
59
+ agno/db/mongo/utils.py,sha256=D173PoWr6CF9QeLpXOuENIM8rzK8d__Kj3fJIPwMEW8,6902
60
60
  agno/db/mysql/__init__.py,sha256=ohBMZ1E6ctioEF0XX5PjC4LtUQrc6lFkjsE4ojyXA8g,63
61
- agno/db/mysql/mysql.py,sha256=Xg1K6jjqbbDZD5uHQbl8R2TPn61eCJsWRb_Y3fJJs2c,86614
61
+ agno/db/mysql/mysql.py,sha256=kP2XlzodZgWeQdyP6kDnla72d0U_r5uXgjA7X_neXhk,86151
62
62
  agno/db/mysql/schemas.py,sha256=2OAaX7ILykFCJBcEWH6kFXzNI8JnnYZCXClbVUoRbLc,5482
63
63
  agno/db/mysql/utils.py,sha256=7E83u2gKOkr7lxFPGM2ucLvfJarbEtNRxOeZQhLYKzU,10066
64
64
  agno/db/postgres/__init__.py,sha256=eEdY4emRxmBmxeZUhAYSaObgcqKdd6C9IxUSk1U0gDY,75
65
- agno/db/postgres/postgres.py,sha256=YNhL3jiSX-9uYzrGUYpJlzWQ0HeN26pcx9HpYPkPGiU,82524
65
+ agno/db/postgres/postgres.py,sha256=bnz-FG-x_mNwlvCHtrZcdbtGeKLJskj1mavpPZoY6jY,82101
66
66
  agno/db/postgres/schemas.py,sha256=adbKcMapqeXsEYeF6feWe2ja1paRzCMOkQSHHN6Psp8,5275
67
67
  agno/db/postgres/utils.py,sha256=iaY0ZqJgzadCitxSbsRchCtBE5WeUApfIj-VbdH9MJI,9447
68
68
  agno/db/redis/__init__.py,sha256=rZWeZ4CpVeKP-enVQ-SRoJ777i0rdGNgoNDRS9gsfAc,63
@@ -76,12 +76,18 @@ agno/db/schemas/memory.py,sha256=kKlJ6AWpbwz-ZJfBJieartPP0QqeeoKAXx2Ity4Yj-Y,146
76
76
  agno/db/schemas/metrics.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
77
  agno/db/singlestore/__init__.py,sha256=dufbaod8ZZIeZIVi0hYJQ8Eu2DfIfWdIy00cpqAsx9U,87
78
78
  agno/db/singlestore/schemas.py,sha256=yDXBGtswAuVxKX1_GvKIBt6IlEor2HiAbYPrwX5SSJ8,5489
79
- agno/db/singlestore/singlestore.py,sha256=t3zp1Nf2RIDt2LtaAMeyyLKn0cymQCDK-ZjT-vcuzhs,83267
79
+ agno/db/singlestore/singlestore.py,sha256=YlugM8NEVLClL2tcpplIv2crwpdGc-jiqtzxxK87AGs,84072
80
80
  agno/db/singlestore/utils.py,sha256=LG0NhOx5B5oJY-Kcc_3ipNzBT1J-mBGx8TARUkRtWv8,11377
81
81
  agno/db/sqlite/__init__.py,sha256=LocJ-suv6xpdun8HUxgbD3bTgmQArQvLJkbpb1pRGy0,67
82
82
  agno/db/sqlite/schemas.py,sha256=-L3hmlg80PAPmfexPrWtnepSzlmZHrbyPZ754nJlVdE,5191
83
- agno/db/sqlite/sqlite.py,sha256=3IVpSiqosz-kTZcsw5ELxICc6Z6e039RyJbVVMV7vC4,84555
83
+ agno/db/sqlite/sqlite.py,sha256=zhCY_bOsKfH5dAsi2FJGGjnSW4SiupywZplSj7DqAsc,84074
84
84
  agno/db/sqlite/utils.py,sha256=DgG9G2g37ry9KscNOdi5AC8DYlSEbIAlRI0qGMfTyIs,9637
85
+ agno/db/surrealdb/__init__.py,sha256=C8qp5-Nx9YnSmgKEtGua-sqG_ntCXONBw1qqnNyKPqI,75
86
+ agno/db/surrealdb/metrics.py,sha256=oKDRyjRQ6KR3HaO8zDHQLVMG7-0NDkOFOKX5I7mD5FA,10336
87
+ agno/db/surrealdb/models.py,sha256=tFQMiVp4FH0WSHI6Co5TLTa76oUB8fTnpRG5eFUQslc,9507
88
+ agno/db/surrealdb/queries.py,sha256=s__yJSFIx387IEflcDdti7T5j6H9NX_-zIj13F9CN9s,2051
89
+ agno/db/surrealdb/surrealdb.py,sha256=uUySaUstsmejAwz5lrAWiMXC5KO8k2TO1lypj63HDu4,46095
90
+ agno/db/surrealdb/utils.py,sha256=CtgL48uFXsh-tQgWHtakH78QT4Z9LZTrhP15C6oIJds,3160
85
91
  agno/eval/__init__.py,sha256=vCYcIbfOkT2lL8vZJ9zsea6j3byp5A-mxEb_45VaD8I,449
86
92
  agno/eval/accuracy.py,sha256=vfJ9Kx33YGsXenNKVHPK5h0IeB2tZMlfSKu6OA-mj9g,33065
87
93
  agno/eval/performance.py,sha256=b4BuSlGkraym9EQick4KraA1OyMa0U7LMjoFozpNbIs,30528
@@ -154,7 +160,7 @@ agno/knowledge/reranker/cohere.py,sha256=2Be5blVyeZ3vYlnFa2NYvJuytjaCB8G2OWJ11pQ
154
160
  agno/knowledge/reranker/infinity.py,sha256=N9geg9xZqRdJZksfQcvbGJgMymXrQVJl_K5KICWqH8o,7193
155
161
  agno/knowledge/reranker/sentence_transformer.py,sha256=ZN4SqnMZsUhg5G7AzlONM1_UjezfNrjFYXpNVHD4U-U,1912
156
162
  agno/memory/__init__.py,sha256=XWKJU5SJObYZqEKMZ2XYwgH8-YeuWUoSRfT4dEI5HnY,101
157
- agno/memory/manager.py,sha256=fgeO5e18qrjotFKM_qClPHmGbGBMwArTKalsG-tdUXo,51065
163
+ agno/memory/manager.py,sha256=jq8buSqZ8r61LcQtvbO1RD7a_FylYbAJMGj_3Yopr7o,51153
158
164
  agno/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
159
165
  agno/models/base.py,sha256=bjP0Xt5-Jlk1I_7wHmuv8lhUPE75WzZ_iF3U-d81TUI,85214
160
166
  agno/models/defaults.py,sha256=1_fe4-ZbNriE8BgqxVRVi4KGzEYxYKYsz4hn6CZNEEM,40
@@ -253,7 +259,7 @@ agno/os/mcp.py,sha256=vJhjjSm1KC61HLoxPj24lSrjkjo7plkoFfcQX2BmTp0,10253
253
259
  agno/os/router.py,sha256=eRxyRX9FjgxtaYwrtNCJLiWH2m6gx6L5zYCff1Gv1ew,71106
254
260
  agno/os/schema.py,sha256=Jlm-vM79iyj-cytWkyKFC4BN4kQV-IaiDqTujvdRzEk,39895
255
261
  agno/os/settings.py,sha256=Cn5_8lZI8Vx1UaUYqs9h6Qp4IMDFn4f3c35uppiaMy4,1343
256
- agno/os/utils.py,sha256=QbSdAI7F4vtbMrTRaeqSHPPbq59yUb8ZStNtTtDtAXA,20018
262
+ agno/os/utils.py,sha256=V6PqoPaUbj1O6O2_vvLZAmKalInh5_Nn3twdYxF5XB0,19996
257
263
  agno/os/interfaces/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
258
264
  agno/os/interfaces/base.py,sha256=vXkr1tRjWHTcmBlQFzvQjqURLhObmFtUAx82uij_j48,542
259
265
  agno/os/interfaces/a2a/__init__.py,sha256=Fs7--dx9drvtVS9QjsCCm0P7c-hJ7TzU8gNwKTQsZDA,62
@@ -317,7 +323,7 @@ agno/session/summary.py,sha256=THBbzE48V81p4dKUX2W8OvbpsNO5dI6BdtqDyjfcVqw,8433
317
323
  agno/session/team.py,sha256=0lS-9ljtG17iyC0n8sq_7aEy9MZsdfMf8VgObqJ_3tg,10384
318
324
  agno/session/workflow.py,sha256=tluE_3ERMBYJtffpwlrhdETWlzJk6Xw2x06FZ1Y3fXg,7397
319
325
  agno/team/__init__.py,sha256=toHidBOo5M3n_TIVtIKHgcDbLL9HR-_U-YQYuIt_XtE,847
320
- agno/team/team.py,sha256=FHMS_CMRzpDjGrwGDvnyHfIS8EMQrVR3yrNbbDbQDJY,372209
326
+ agno/team/team.py,sha256=BUZiXYF5mJoMHDW5SRPGwaTv54_cIusWLpZ-WdjX9Tg,374472
321
327
  agno/tools/__init__.py,sha256=jNll2sELhPPbqm5nPeT4_uyzRO2_KRTW-8Or60kioS0,210
322
328
  agno/tools/agentql.py,sha256=S82Z9aTNr-E5wnA4fbFs76COljJtiQIjf2grjz3CkHU,4104
323
329
  agno/tools/airflow.py,sha256=uf2rOzZpSU64l_qRJ5Raku-R3Gky-uewmYkh6W0-oxg,2610
@@ -531,7 +537,7 @@ agno/vectordb/singlestore/__init__.py,sha256=Cuaq_pvpX5jsUv3tWlOFnlrF4VGykGIIK5h
531
537
  agno/vectordb/singlestore/index.py,sha256=p9LYQlVINlZZvZORfiDE3AIFinx07idDHr9_mM3EXAg,1527
532
538
  agno/vectordb/singlestore/singlestore.py,sha256=WFP8rvE3azf2QsXicQTibZ7Omcy2XWgJ_OVOUJJR4mA,30708
533
539
  agno/vectordb/surrealdb/__init__.py,sha256=4GIpJZH0Hb42s1ZR0VS5BQ5RhTAaolmS-_rAIYn9poM,81
534
- agno/vectordb/surrealdb/surrealdb.py,sha256=V8fZXW8jvrNZ0oWP7ag2Hlu-MY6Oa4L858cKVEvM7FM,25428
540
+ agno/vectordb/surrealdb/surrealdb.py,sha256=pgSM83HCgfcNo8CDBfsB5PP4y8qwvfFAD1Zv_gpj7kM,25359
535
541
  agno/vectordb/upstashdb/__init__.py,sha256=set3Sx1F3ZCw0--0AeC036EAS0cC1xKsvQUK5FyloFA,100
536
542
  agno/vectordb/upstashdb/upstashdb.py,sha256=ggFcNzQ1X47zWPGM6OhUdvOuG0A8JmrhkAkX7q2opD4,29030
537
543
  agno/vectordb/weaviate/__init__.py,sha256=FIoFJgqSmGuFgpvmsg8EjAn8FDAhuqAXed7fjaW4exY,182
@@ -542,12 +548,12 @@ agno/workflow/condition.py,sha256=MgJnHRPEJ2qCjUkcHKyZfOuAn-C38ZTgVcYjY8iTgrI,30
542
548
  agno/workflow/loop.py,sha256=q2XssC179htRC7KPiebUcvr0lKexfZUB9aUO4D3tOrk,32305
543
549
  agno/workflow/parallel.py,sha256=Gb6XZbwDJgmBBbuiZTFHvphQqrsMVgM-HTOMoiIHweg,34843
544
550
  agno/workflow/router.py,sha256=-gPT43a1mP0tnE6wQa4tEAuGWNppel8DbmCg0ajo-L0,28295
545
- agno/workflow/step.py,sha256=VIAm6SQYANva2ppYZPcDjr_nP4iGQSuOOt-0mq3FABk,58497
551
+ agno/workflow/step.py,sha256=phA5pfhDR_0rie-85WUoM8toGO7tVfP4nzfqOjGBrxI,58931
546
552
  agno/workflow/steps.py,sha256=1qOcH0SuPTPE0Ac3sRyRLjFoMcKyTo44hlJXdbOBNnM,25389
547
553
  agno/workflow/types.py,sha256=DutB4UkEppJoWRiNaGEnPk6xFNpg0oCBwOb7VJ8T_xE,18646
548
554
  agno/workflow/workflow.py,sha256=AD2mKXap840IwPb2WMnVJM30lQLAFUfWxd7nqQJ52hU,137906
549
- agno-2.1.5.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
550
- agno-2.1.5.dist-info/METADATA,sha256=hdT3NEhb3E4c67BIzIPPA9U0xqpyqENrfYxRtizglwI,24504
551
- agno-2.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
552
- agno-2.1.5.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
553
- agno-2.1.5.dist-info/RECORD,,
555
+ agno-2.1.6.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
556
+ agno-2.1.6.dist-info/METADATA,sha256=xLKz0Cbdnw7Q9c2IjtAe2vsNbXI3NNHzXAvLA6oRJSg,24504
557
+ agno-2.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
558
+ agno-2.1.6.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
559
+ agno-2.1.6.dist-info/RECORD,,
File without changes