agno 1.7.4__py3-none-any.whl → 1.7.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 +28 -15
- agno/app/agui/async_router.py +5 -5
- agno/app/agui/sync_router.py +5 -5
- agno/app/agui/utils.py +84 -14
- agno/app/fastapi/app.py +1 -1
- agno/app/fastapi/async_router.py +67 -16
- agno/app/fastapi/sync_router.py +80 -14
- agno/document/chunking/row.py +39 -0
- agno/document/reader/base.py +0 -7
- agno/embedder/jina.py +73 -0
- agno/knowledge/agent.py +39 -2
- agno/knowledge/combined.py +1 -1
- agno/memory/agent.py +2 -2
- agno/memory/team.py +2 -2
- agno/models/aws/bedrock.py +311 -15
- agno/models/litellm/chat.py +12 -3
- agno/models/openai/chat.py +1 -22
- agno/models/openai/responses.py +5 -5
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +88 -0
- agno/models/xai/xai.py +54 -0
- agno/run/v2/workflow.py +4 -0
- agno/storage/mysql.py +1 -0
- agno/storage/postgres.py +1 -0
- agno/storage/session/v2/workflow.py +29 -5
- agno/storage/singlestore.py +4 -1
- agno/storage/sqlite.py +0 -1
- agno/team/team.py +52 -22
- agno/tools/bitbucket.py +292 -0
- agno/tools/daytona.py +411 -63
- agno/tools/decorator.py +45 -2
- agno/tools/evm.py +123 -0
- agno/tools/function.py +16 -12
- agno/tools/linkup.py +54 -0
- agno/tools/mcp.py +10 -3
- agno/tools/mem0.py +15 -2
- agno/tools/postgres.py +175 -162
- agno/utils/log.py +16 -0
- agno/utils/pprint.py +2 -0
- agno/utils/string.py +14 -0
- agno/vectordb/pgvector/pgvector.py +4 -5
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +493 -0
- agno/workflow/v2/workflow.py +144 -19
- agno/workflow/workflow.py +90 -63
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/METADATA +19 -1
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/RECORD +51 -42
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/WHEEL +0 -0
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/entry_points.txt +0 -0
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/licenses/LICENSE +0 -0
- {agno-1.7.4.dist-info → agno-1.7.6.dist-info}/top_level.txt +0 -0
agno/tools/evm.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from agno.tools import Toolkit
|
|
5
|
+
from agno.utils.log import log_debug, log_error
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from eth_account.account import LocalAccount
|
|
9
|
+
from eth_account.datastructures import SignedTransaction
|
|
10
|
+
from hexbytes import HexBytes
|
|
11
|
+
from web3 import Web3
|
|
12
|
+
from web3.main import Web3 as Web3Type
|
|
13
|
+
from web3.providers.rpc import HTTPProvider
|
|
14
|
+
from web3.types import TxParams, TxReceipt
|
|
15
|
+
except ImportError:
|
|
16
|
+
raise ImportError("`web3` not installed. Please install using `pip install web3`")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class EvmTools(Toolkit):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
private_key: Optional[str] = None,
|
|
23
|
+
rpc_url: Optional[str] = None,
|
|
24
|
+
**kwargs,
|
|
25
|
+
):
|
|
26
|
+
"""Initialize EVM tools for blockchain interactions.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
private_key: Private key for signing transactions (defaults to EVM_PRIVATE_KEY env var)
|
|
30
|
+
rpc_url: RPC URL for blockchain connection (defaults to EVM_RPC_URL env var)
|
|
31
|
+
**kwargs: Additional arguments passed to parent Toolkit class
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
self.private_key = private_key or getenv("EVM_PRIVATE_KEY")
|
|
35
|
+
self.rpc_url = rpc_url or getenv("EVM_RPC_URL")
|
|
36
|
+
|
|
37
|
+
if not self.private_key:
|
|
38
|
+
log_error("Private Key is required")
|
|
39
|
+
raise ValueError("Private Key is required")
|
|
40
|
+
if not self.rpc_url:
|
|
41
|
+
log_error("RPC Url is needed to interact with EVM blockchain")
|
|
42
|
+
raise ValueError("RPC Url is needed to interact with EVM blockchain")
|
|
43
|
+
|
|
44
|
+
# Ensure private key has 0x prefix
|
|
45
|
+
if not self.private_key.startswith("0x"):
|
|
46
|
+
self.private_key = f"0x{self.private_key}"
|
|
47
|
+
|
|
48
|
+
# Initialize Web3 client and account
|
|
49
|
+
self.web3_client: "Web3Type" = Web3(HTTPProvider(self.rpc_url))
|
|
50
|
+
self.account: "LocalAccount" = self.web3_client.eth.account.from_key(self.private_key)
|
|
51
|
+
log_debug(f"Your wallet address is: {self.account.address}")
|
|
52
|
+
|
|
53
|
+
super().__init__(name="evm_tools", tools=[self.send_transaction], **kwargs)
|
|
54
|
+
|
|
55
|
+
def get_max_priority_fee_per_gas(self) -> int:
|
|
56
|
+
"""Get the max priority fee per gas for the transaction.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
int: The max priority fee per gas for the transaction (1 gwei)
|
|
60
|
+
"""
|
|
61
|
+
max_priority_fee_per_gas = self.web3_client.to_wei(1, "gwei")
|
|
62
|
+
return max_priority_fee_per_gas
|
|
63
|
+
|
|
64
|
+
def get_max_fee_per_gas(self, max_priority_fee_per_gas: int) -> int:
|
|
65
|
+
"""Get the max fee per gas for the transaction.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
max_priority_fee_per_gas: The max priority fee per gas
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
int: The max fee per gas for the transaction
|
|
72
|
+
"""
|
|
73
|
+
latest_block = self.web3_client.eth.get_block("latest")
|
|
74
|
+
base_fee_per_gas = latest_block.get("baseFeePerGas")
|
|
75
|
+
if base_fee_per_gas is None:
|
|
76
|
+
log_error("Base fee per gas not found in the latest block.")
|
|
77
|
+
raise ValueError("Base fee per gas not found in the latest block.")
|
|
78
|
+
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas
|
|
79
|
+
return max_fee_per_gas
|
|
80
|
+
|
|
81
|
+
def send_transaction(self, to_address: str, amount_in_wei: int) -> str:
|
|
82
|
+
"""Sends a transaction to the address provided.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
to_address: The address to which you want to send ETH
|
|
86
|
+
amount_in_wei: The amount of ETH to send in wei
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
str: The transaction hash of the transaction or error message
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
max_priority_fee_per_gas = self.get_max_priority_fee_per_gas()
|
|
93
|
+
max_fee_per_gas = self.get_max_fee_per_gas(max_priority_fee_per_gas)
|
|
94
|
+
|
|
95
|
+
transaction_params: "TxParams" = {
|
|
96
|
+
"from": self.account.address,
|
|
97
|
+
"to": to_address,
|
|
98
|
+
"value": amount_in_wei, # type: ignore[typeddict-item]
|
|
99
|
+
"nonce": self.web3_client.eth.get_transaction_count(self.account.address),
|
|
100
|
+
"gas": 21000,
|
|
101
|
+
"maxFeePerGas": max_fee_per_gas, # type: ignore[typeddict-item]
|
|
102
|
+
"maxPriorityFeePerGas": max_priority_fee_per_gas, # type: ignore[typeddict-item]
|
|
103
|
+
"chainId": self.web3_client.eth.chain_id,
|
|
104
|
+
"type": 2, # EIP-1559 dynamic fee transaction
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
signed_transaction: "SignedTransaction" = self.web3_client.eth.account.sign_transaction(
|
|
108
|
+
transaction_params, self.private_key
|
|
109
|
+
)
|
|
110
|
+
transaction_hash: "HexBytes" = self.web3_client.eth.send_raw_transaction(signed_transaction.raw_transaction)
|
|
111
|
+
log_debug(f"Ongoing Transaction hash: 0x{transaction_hash.hex()}")
|
|
112
|
+
|
|
113
|
+
transaction_receipt: "TxReceipt" = self.web3_client.eth.wait_for_transaction_receipt(transaction_hash)
|
|
114
|
+
if transaction_receipt.get("status") == 1:
|
|
115
|
+
log_debug(f"Transaction successful! Transaction hash: 0x{transaction_hash.hex()}")
|
|
116
|
+
return f"0x{transaction_hash.hex()}"
|
|
117
|
+
else:
|
|
118
|
+
log_error("Transaction failed!")
|
|
119
|
+
raise Exception("Transaction failed!")
|
|
120
|
+
|
|
121
|
+
except Exception as e:
|
|
122
|
+
log_error(f"Error sending transaction: {e}")
|
|
123
|
+
return f"error: {e}"
|
agno/tools/function.py
CHANGED
|
@@ -151,7 +151,7 @@ class Function(BaseModel):
|
|
|
151
151
|
param_type_hints = {
|
|
152
152
|
name: type_hints.get(name)
|
|
153
153
|
for name in sig.parameters
|
|
154
|
-
if name != "return" and name not in ["agent", "team"]
|
|
154
|
+
if name != "return" and name not in ["agent", "team", "self"]
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
# Parse docstring for parameters
|
|
@@ -177,7 +177,9 @@ class Function(BaseModel):
|
|
|
177
177
|
# If strict=True mark all fields as required
|
|
178
178
|
# See: https://platform.openai.com/docs/guides/structured-outputs/supported-schemas#all-fields-must-be-required
|
|
179
179
|
if strict:
|
|
180
|
-
parameters["required"] = [
|
|
180
|
+
parameters["required"] = [
|
|
181
|
+
name for name in parameters["properties"] if name not in ["agent", "team", "self"]
|
|
182
|
+
]
|
|
181
183
|
else:
|
|
182
184
|
# Mark a field as required if it has no default value (this would include optional fields)
|
|
183
185
|
parameters["required"] = [
|
|
@@ -235,7 +237,7 @@ class Function(BaseModel):
|
|
|
235
237
|
# log_info(f"Type hints for {self.name}: {type_hints}")
|
|
236
238
|
|
|
237
239
|
# Filter out return type and only process parameters
|
|
238
|
-
excluded_params = ["return", "agent", "team"]
|
|
240
|
+
excluded_params = ["return", "agent", "team", "self"]
|
|
239
241
|
if self.requires_user_input and self.user_input_fields:
|
|
240
242
|
if len(self.user_input_fields) == 0:
|
|
241
243
|
excluded_params.extend(list(type_hints.keys()))
|
|
@@ -337,7 +339,9 @@ class Function(BaseModel):
|
|
|
337
339
|
|
|
338
340
|
def process_schema_for_strict(self):
|
|
339
341
|
self.parameters["additionalProperties"] = False
|
|
340
|
-
self.parameters["required"] = [
|
|
342
|
+
self.parameters["required"] = [
|
|
343
|
+
name for name in self.parameters["properties"] if name not in ["agent", "team", "self"]
|
|
344
|
+
]
|
|
341
345
|
|
|
342
346
|
def _get_cache_key(self, entrypoint_args: Dict[str, Any], call_args: Optional[Dict[str, Any]] = None) -> str:
|
|
343
347
|
"""Generate a cache key based on function name and arguments."""
|
|
@@ -554,7 +558,7 @@ class FunctionCall(BaseModel):
|
|
|
554
558
|
from functools import reduce
|
|
555
559
|
from inspect import iscoroutinefunction
|
|
556
560
|
|
|
557
|
-
def execute_entrypoint():
|
|
561
|
+
def execute_entrypoint(name, func, args):
|
|
558
562
|
"""Execute the entrypoint function."""
|
|
559
563
|
arguments = entrypoint_args.copy()
|
|
560
564
|
if self.arguments is not None:
|
|
@@ -572,9 +576,9 @@ class FunctionCall(BaseModel):
|
|
|
572
576
|
# Pass the inner function as next_func to the hook
|
|
573
577
|
# The hook will call next_func to continue the chain
|
|
574
578
|
def next_func(**kwargs):
|
|
575
|
-
return inner_func()
|
|
579
|
+
return inner_func(name, func, kwargs)
|
|
576
580
|
|
|
577
|
-
hook_args = self._build_hook_args(hook, name,
|
|
581
|
+
hook_args = self._build_hook_args(hook, name, next_func, args)
|
|
578
582
|
|
|
579
583
|
return hook(**hook_args)
|
|
580
584
|
|
|
@@ -716,7 +720,7 @@ class FunctionCall(BaseModel):
|
|
|
716
720
|
from functools import reduce
|
|
717
721
|
from inspect import isasyncgen, isasyncgenfunction, iscoroutinefunction
|
|
718
722
|
|
|
719
|
-
async def execute_entrypoint_async():
|
|
723
|
+
async def execute_entrypoint_async(name, func, args):
|
|
720
724
|
"""Execute the entrypoint function asynchronously."""
|
|
721
725
|
arguments = entrypoint_args.copy()
|
|
722
726
|
if self.arguments is not None:
|
|
@@ -729,7 +733,7 @@ class FunctionCall(BaseModel):
|
|
|
729
733
|
result = await result
|
|
730
734
|
return result
|
|
731
735
|
|
|
732
|
-
def execute_entrypoint():
|
|
736
|
+
def execute_entrypoint(name, func, args):
|
|
733
737
|
"""Execute the entrypoint function synchronously."""
|
|
734
738
|
arguments = entrypoint_args.copy()
|
|
735
739
|
if self.arguments is not None:
|
|
@@ -750,11 +754,11 @@ class FunctionCall(BaseModel):
|
|
|
750
754
|
# The hook will call next_func to continue the chain
|
|
751
755
|
async def next_func(**kwargs):
|
|
752
756
|
if iscoroutinefunction(inner_func):
|
|
753
|
-
return await inner_func()
|
|
757
|
+
return await inner_func(name, func, kwargs)
|
|
754
758
|
else:
|
|
755
|
-
return inner_func()
|
|
759
|
+
return inner_func(name, func, kwargs)
|
|
756
760
|
|
|
757
|
-
hook_args = self._build_hook_args(hook, name,
|
|
761
|
+
hook_args = self._build_hook_args(hook, name, next_func, args)
|
|
758
762
|
|
|
759
763
|
if iscoroutinefunction(hook):
|
|
760
764
|
return await hook(**hook_args)
|
agno/tools/linkup.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Any, List, Literal, Optional
|
|
3
|
+
|
|
4
|
+
from agno.tools import Toolkit
|
|
5
|
+
from agno.utils.log import logger
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from linkup import LinkupClient
|
|
9
|
+
except ImportError:
|
|
10
|
+
raise ImportError("`linkup-sdk` not installed. Please install using `pip install linkup-sdk`")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LinkupTools(Toolkit):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
api_key: Optional[str] = None,
|
|
17
|
+
depth: Literal["standard", "deep"] = "standard",
|
|
18
|
+
output_type: Literal["sourcedAnswer", "searchResults"] = "searchResults",
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
self.api_key = api_key or getenv("LINKUP_API_KEY")
|
|
22
|
+
if not self.api_key:
|
|
23
|
+
logger.error("LINKUP_API_KEY not set. Please set the LINKUP_API_KEY environment variable.")
|
|
24
|
+
|
|
25
|
+
self.linkup = LinkupClient(api_key=api_key)
|
|
26
|
+
self.depth = depth
|
|
27
|
+
self.output_type = output_type
|
|
28
|
+
|
|
29
|
+
tools: List[Any] = [self.web_search_with_linkup]
|
|
30
|
+
|
|
31
|
+
super().__init__(name="linkup_tools", tools=tools, **kwargs)
|
|
32
|
+
|
|
33
|
+
def web_search_with_linkup(self, query: str, depth: Optional[str] = None, output_type: Optional[str] = None) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Use this function to search the web for a given query.
|
|
36
|
+
This function uses the Linkup API to provide realtime online information about the query.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
query (str): Query to search for.
|
|
40
|
+
depth (str): (deep|standard) Depth of the search. Defaults to 'standard'.
|
|
41
|
+
output_type (str): (sourcedAnswer|searchResults) Type of output. Defaults to 'searchResults'.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: string of results related to the query.
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
response = self.linkup.search(
|
|
48
|
+
query=query,
|
|
49
|
+
depth=depth or self.depth, # type: ignore
|
|
50
|
+
output_type=output_type or self.output_type, # type: ignore
|
|
51
|
+
)
|
|
52
|
+
return response
|
|
53
|
+
except Exception as e:
|
|
54
|
+
return f"Error: {str(e)}"
|
agno/tools/mcp.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Literal, Optional, Union
|
|
|
6
6
|
|
|
7
7
|
from agno.tools import Toolkit
|
|
8
8
|
from agno.tools.function import Function
|
|
9
|
-
from agno.utils.log import log_debug, log_warning, logger
|
|
9
|
+
from agno.utils.log import log_debug, log_info, log_warning, logger
|
|
10
10
|
from agno.utils.mcp import get_entrypoint_for_tool
|
|
11
11
|
|
|
12
12
|
try:
|
|
@@ -82,6 +82,9 @@ class MCPTools(Toolkit):
|
|
|
82
82
|
"""
|
|
83
83
|
super().__init__(name="MCPTools", **kwargs)
|
|
84
84
|
|
|
85
|
+
if transport == "sse":
|
|
86
|
+
log_info("SSE as a standalone transport is deprecated. Please use Streamable HTTP instead.")
|
|
87
|
+
|
|
85
88
|
# Set these after `__init__` to bypass the `_check_tools_filters`
|
|
86
89
|
# because tools are not available until `initialize()` is called.
|
|
87
90
|
self.include_tools = include_tools
|
|
@@ -303,10 +306,14 @@ class MultiMCPTools(Toolkit):
|
|
|
303
306
|
"""
|
|
304
307
|
super().__init__(name="MultiMCPTools", **kwargs)
|
|
305
308
|
|
|
309
|
+
if urls_transports is not None:
|
|
310
|
+
if "sse" in urls_transports:
|
|
311
|
+
log_info("SSE as a standalone transport is deprecated. Please use Streamable HTTP instead.")
|
|
312
|
+
|
|
306
313
|
if urls is not None:
|
|
307
314
|
if urls_transports is None:
|
|
308
315
|
log_warning(
|
|
309
|
-
"The default transport '
|
|
316
|
+
"The default transport 'streamable-http' will be used. You can explicitly set the transports by providing the urls_transports parameter."
|
|
310
317
|
)
|
|
311
318
|
else:
|
|
312
319
|
if len(urls) != len(urls_transports):
|
|
@@ -355,7 +362,7 @@ class MultiMCPTools(Toolkit):
|
|
|
355
362
|
self.server_params_list.append(SSEClientParams(url=url))
|
|
356
363
|
else:
|
|
357
364
|
for url in urls:
|
|
358
|
-
self.server_params_list.append(
|
|
365
|
+
self.server_params_list.append(StreamableHTTPClientParams(url=url))
|
|
359
366
|
|
|
360
367
|
self._async_exit_stack = AsyncExitStack()
|
|
361
368
|
|
agno/tools/mem0.py
CHANGED
|
@@ -7,7 +7,8 @@ from agno.tools.toolkit import Toolkit
|
|
|
7
7
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
8
8
|
|
|
9
9
|
try:
|
|
10
|
-
from mem0 import
|
|
10
|
+
from mem0.client.main import MemoryClient
|
|
11
|
+
from mem0.memory.main import Memory
|
|
11
12
|
except ImportError:
|
|
12
13
|
raise ImportError("`mem0ai` package not found. Please install it with `pip install mem0ai`")
|
|
13
14
|
|
|
@@ -18,6 +19,8 @@ class Mem0Tools(Toolkit):
|
|
|
18
19
|
config: Optional[Dict[str, Any]] = None,
|
|
19
20
|
api_key: Optional[str] = None,
|
|
20
21
|
user_id: Optional[str] = None,
|
|
22
|
+
org_id: Optional[str] = None,
|
|
23
|
+
project_id: Optional[str] = None,
|
|
21
24
|
infer: bool = True,
|
|
22
25
|
**kwargs,
|
|
23
26
|
):
|
|
@@ -33,13 +36,20 @@ class Mem0Tools(Toolkit):
|
|
|
33
36
|
)
|
|
34
37
|
self.api_key = api_key or getenv("MEM0_API_KEY")
|
|
35
38
|
self.user_id = user_id
|
|
39
|
+
self.org_id = org_id or getenv("MEM0_ORG_ID")
|
|
40
|
+
self.project_id = project_id or getenv("MEM0_PROJECT_ID")
|
|
36
41
|
self.client: Union[Memory, MemoryClient]
|
|
37
42
|
self.infer = infer
|
|
38
43
|
|
|
39
44
|
try:
|
|
40
45
|
if self.api_key:
|
|
41
46
|
log_debug("Using Mem0 Platform API key.")
|
|
42
|
-
|
|
47
|
+
client_kwargs = {"api_key": self.api_key}
|
|
48
|
+
if self.org_id:
|
|
49
|
+
client_kwargs["org_id"] = self.org_id
|
|
50
|
+
if self.project_id:
|
|
51
|
+
client_kwargs["project_id"] = self.project_id
|
|
52
|
+
self.client = MemoryClient(**client_kwargs)
|
|
43
53
|
elif config is not None:
|
|
44
54
|
log_debug("Using Mem0 with config.")
|
|
45
55
|
self.client = Memory.from_config(config)
|
|
@@ -100,6 +110,7 @@ class Mem0Tools(Toolkit):
|
|
|
100
110
|
messages_list,
|
|
101
111
|
user_id=resolved_user_id,
|
|
102
112
|
infer=self.infer,
|
|
113
|
+
output_format="v1.1",
|
|
103
114
|
)
|
|
104
115
|
return json.dumps(result)
|
|
105
116
|
except Exception as e:
|
|
@@ -120,6 +131,7 @@ class Mem0Tools(Toolkit):
|
|
|
120
131
|
results = self.client.search(
|
|
121
132
|
query=query,
|
|
122
133
|
user_id=resolved_user_id,
|
|
134
|
+
output_format="v1.1",
|
|
123
135
|
)
|
|
124
136
|
|
|
125
137
|
if isinstance(results, dict) and "results" in results:
|
|
@@ -147,6 +159,7 @@ class Mem0Tools(Toolkit):
|
|
|
147
159
|
try:
|
|
148
160
|
results = self.client.get_all(
|
|
149
161
|
user_id=resolved_user_id,
|
|
162
|
+
output_format="v1.1",
|
|
150
163
|
)
|
|
151
164
|
|
|
152
165
|
if isinstance(results, dict) and "results" in results:
|