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.
- agno/agent/agent.py +37 -32
- agno/db/migrations/v1_to_v2.py +13 -0
- agno/db/mongo/mongo.py +2 -6
- agno/db/mongo/utils.py +0 -4
- agno/db/mysql/mysql.py +4 -16
- agno/db/postgres/postgres.py +8 -20
- agno/db/singlestore/singlestore.py +17 -8
- agno/db/sqlite/sqlite.py +4 -16
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +259 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1193 -0
- agno/db/surrealdb/utils.py +87 -0
- agno/memory/manager.py +13 -13
- agno/os/utils.py +8 -10
- agno/team/team.py +88 -42
- agno/vectordb/surrealdb/surrealdb.py +0 -1
- agno/workflow/step.py +8 -0
- {agno-2.1.5.dist-info → agno-2.1.6.dist-info}/METADATA +1 -1
- {agno-2.1.5.dist-info → agno-2.1.6.dist-info}/RECORD +24 -18
- {agno-2.1.5.dist-info → agno-2.1.6.dist-info}/WHEEL +0 -0
- {agno-2.1.5.dist-info → agno-2.1.6.dist-info}/licenses/LICENSE +0 -0
- {agno-2.1.5.dist-info → agno-2.1.6.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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
|
|
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
|
-
"
|
|
761
|
+
" - Decide to make no changes.",
|
|
762
762
|
]
|
|
763
763
|
if enable_add_memory:
|
|
764
|
-
system_prompt_lines.append("
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
3684
|
-
This
|
|
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
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
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
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
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.
|
|
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
|
-
#
|
|
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"]
|
|
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
|
|
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
|
|
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
|
|
7347
|
-
if
|
|
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
|
-
|
|
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)):
|
|
@@ -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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
550
|
-
agno-2.1.
|
|
551
|
-
agno-2.1.
|
|
552
|
-
agno-2.1.
|
|
553
|
-
agno-2.1.
|
|
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
|
|
File without changes
|
|
File without changes
|