agno 2.2.0__py3-none-any.whl → 2.2.2__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 +751 -575
- agno/culture/manager.py +22 -24
- agno/db/async_postgres/__init__.py +1 -1
- agno/db/dynamo/dynamo.py +0 -2
- agno/db/firestore/firestore.py +0 -2
- agno/db/gcs_json/gcs_json_db.py +0 -4
- agno/db/gcs_json/utils.py +0 -24
- agno/db/in_memory/in_memory_db.py +0 -3
- agno/db/json/json_db.py +4 -10
- agno/db/json/utils.py +0 -24
- agno/db/mongo/mongo.py +0 -2
- agno/db/mysql/mysql.py +0 -3
- agno/db/postgres/__init__.py +1 -1
- agno/db/{async_postgres → postgres}/async_postgres.py +19 -22
- agno/db/postgres/postgres.py +7 -10
- agno/db/postgres/utils.py +106 -2
- agno/db/redis/redis.py +0 -2
- agno/db/singlestore/singlestore.py +0 -3
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2269 -0
- agno/db/sqlite/sqlite.py +0 -2
- agno/db/sqlite/utils.py +96 -0
- agno/db/surrealdb/surrealdb.py +0 -6
- agno/knowledge/knowledge.py +14 -3
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +30 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/types.py +1 -0
- agno/memory/manager.py +28 -25
- agno/models/anthropic/claude.py +63 -6
- agno/models/base.py +255 -36
- agno/models/response.py +69 -0
- agno/os/router.py +7 -5
- agno/os/routers/memory/memory.py +2 -1
- agno/os/routers/memory/schemas.py +5 -2
- agno/os/schema.py +26 -20
- agno/os/utils.py +9 -2
- agno/run/agent.py +28 -30
- agno/run/base.py +17 -1
- agno/run/team.py +28 -29
- agno/run/workflow.py +32 -17
- agno/session/agent.py +3 -0
- agno/session/summary.py +4 -1
- agno/session/team.py +1 -1
- agno/team/team.py +620 -374
- agno/tools/dalle.py +2 -4
- agno/tools/eleven_labs.py +23 -25
- agno/tools/function.py +40 -0
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +324 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/slack.py +18 -3
- agno/tools/tavily.py +146 -0
- agno/utils/agent.py +366 -1
- agno/utils/mcp.py +92 -2
- agno/utils/media.py +166 -1
- agno/utils/message.py +60 -0
- agno/utils/print_response/workflow.py +17 -1
- agno/utils/team.py +89 -1
- agno/workflow/step.py +0 -1
- agno/workflow/types.py +10 -15
- agno/workflow/workflow.py +86 -1
- {agno-2.2.0.dist-info → agno-2.2.2.dist-info}/METADATA +31 -25
- {agno-2.2.0.dist-info → agno-2.2.2.dist-info}/RECORD +68 -64
- agno/db/async_postgres/schemas.py +0 -139
- agno/db/async_postgres/utils.py +0 -347
- agno/tools/mcp.py +0 -679
- {agno-2.2.0.dist-info → agno-2.2.2.dist-info}/WHEEL +0 -0
- {agno-2.2.0.dist-info → agno-2.2.2.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.0.dist-info → agno-2.2.2.dist-info}/top_level.txt +0 -0
agno/memory/manager.py
CHANGED
|
@@ -89,8 +89,6 @@ class MemoryManager:
|
|
|
89
89
|
self.add_memories = add_memories
|
|
90
90
|
self.clear_memories = clear_memories
|
|
91
91
|
self.debug_mode = debug_mode
|
|
92
|
-
self._tools_for_model: Optional[List[Dict[str, Any]]] = None
|
|
93
|
-
self._functions_for_model: Optional[Dict[str, Function]] = None
|
|
94
92
|
|
|
95
93
|
def get_model(self) -> Model:
|
|
96
94
|
if self.model is None:
|
|
@@ -710,23 +708,26 @@ class MemoryManager:
|
|
|
710
708
|
return sorted_memories_list
|
|
711
709
|
|
|
712
710
|
# --Memory Manager Functions--
|
|
713
|
-
def determine_tools_for_model(self, tools: List[Callable]) ->
|
|
711
|
+
def determine_tools_for_model(self, tools: List[Callable]) -> List[Union[Function, dict]]:
|
|
714
712
|
# Have to reset each time, because of different user IDs
|
|
715
|
-
|
|
716
|
-
|
|
713
|
+
_function_names = []
|
|
714
|
+
_functions: List[Union[Function, dict]] = []
|
|
717
715
|
|
|
718
716
|
for tool in tools:
|
|
719
717
|
try:
|
|
720
718
|
function_name = tool.__name__
|
|
721
|
-
if function_name
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
719
|
+
if function_name in _function_names:
|
|
720
|
+
continue
|
|
721
|
+
_function_names.append(function_name)
|
|
722
|
+
func = Function.from_callable(tool, strict=True) # type: ignore
|
|
723
|
+
func.strict = True
|
|
724
|
+
_functions.append(func)
|
|
725
|
+
log_debug(f"Added function {func.name}")
|
|
727
726
|
except Exception as e:
|
|
728
727
|
log_warning(f"Could not add function {tool}: {e}")
|
|
729
728
|
|
|
729
|
+
return _functions
|
|
730
|
+
|
|
730
731
|
def get_system_message(
|
|
731
732
|
self,
|
|
732
733
|
existing_memories: Optional[List[Dict[str, Any]]] = None,
|
|
@@ -833,7 +834,7 @@ class MemoryManager:
|
|
|
833
834
|
|
|
834
835
|
model_copy = deepcopy(self.model)
|
|
835
836
|
# Update the Model (set defaults, add logit etc.)
|
|
836
|
-
self.determine_tools_for_model(
|
|
837
|
+
_tools = self.determine_tools_for_model(
|
|
837
838
|
self._get_db_tools(
|
|
838
839
|
user_id,
|
|
839
840
|
db,
|
|
@@ -862,8 +863,7 @@ class MemoryManager:
|
|
|
862
863
|
# Generate a response from the Model (includes running function calls)
|
|
863
864
|
response = model_copy.response(
|
|
864
865
|
messages=messages_for_model,
|
|
865
|
-
tools=
|
|
866
|
-
functions=self._functions_for_model,
|
|
866
|
+
tools=_tools,
|
|
867
867
|
)
|
|
868
868
|
|
|
869
869
|
if response.tool_calls is not None and len(response.tool_calls) > 0:
|
|
@@ -897,7 +897,7 @@ class MemoryManager:
|
|
|
897
897
|
model_copy = deepcopy(self.model)
|
|
898
898
|
# Update the Model (set defaults, add logit etc.)
|
|
899
899
|
if isinstance(db, AsyncBaseDb):
|
|
900
|
-
self.determine_tools_for_model(
|
|
900
|
+
_tools = self.determine_tools_for_model(
|
|
901
901
|
await self._aget_db_tools(
|
|
902
902
|
user_id,
|
|
903
903
|
db,
|
|
@@ -911,7 +911,7 @@ class MemoryManager:
|
|
|
911
911
|
),
|
|
912
912
|
)
|
|
913
913
|
else:
|
|
914
|
-
self.determine_tools_for_model(
|
|
914
|
+
_tools = self.determine_tools_for_model(
|
|
915
915
|
self._get_db_tools(
|
|
916
916
|
user_id,
|
|
917
917
|
db,
|
|
@@ -940,8 +940,7 @@ class MemoryManager:
|
|
|
940
940
|
# Generate a response from the Model (includes running function calls)
|
|
941
941
|
response = await model_copy.aresponse(
|
|
942
942
|
messages=messages_for_model,
|
|
943
|
-
tools=
|
|
944
|
-
functions=self._functions_for_model,
|
|
943
|
+
tools=_tools,
|
|
945
944
|
)
|
|
946
945
|
|
|
947
946
|
if response.tool_calls is not None and len(response.tool_calls) > 0:
|
|
@@ -969,7 +968,7 @@ class MemoryManager:
|
|
|
969
968
|
|
|
970
969
|
model_copy = deepcopy(self.model)
|
|
971
970
|
# Update the Model (set defaults, add logit etc.)
|
|
972
|
-
self.determine_tools_for_model(
|
|
971
|
+
_tools = self.determine_tools_for_model(
|
|
973
972
|
self._get_db_tools(
|
|
974
973
|
user_id,
|
|
975
974
|
db,
|
|
@@ -997,8 +996,7 @@ class MemoryManager:
|
|
|
997
996
|
# Generate a response from the Model (includes running function calls)
|
|
998
997
|
response = model_copy.response(
|
|
999
998
|
messages=messages_for_model,
|
|
1000
|
-
tools=
|
|
1001
|
-
functions=self._functions_for_model,
|
|
999
|
+
tools=_tools,
|
|
1002
1000
|
)
|
|
1003
1001
|
|
|
1004
1002
|
if response.tool_calls is not None and len(response.tool_calls) > 0:
|
|
@@ -1027,7 +1025,7 @@ class MemoryManager:
|
|
|
1027
1025
|
model_copy = deepcopy(self.model)
|
|
1028
1026
|
# Update the Model (set defaults, add logit etc.)
|
|
1029
1027
|
if isinstance(db, AsyncBaseDb):
|
|
1030
|
-
self.determine_tools_for_model(
|
|
1028
|
+
_tools = self.determine_tools_for_model(
|
|
1031
1029
|
await self._aget_db_tools(
|
|
1032
1030
|
user_id,
|
|
1033
1031
|
db,
|
|
@@ -1039,7 +1037,7 @@ class MemoryManager:
|
|
|
1039
1037
|
),
|
|
1040
1038
|
)
|
|
1041
1039
|
else:
|
|
1042
|
-
self.determine_tools_for_model(
|
|
1040
|
+
_tools = self.determine_tools_for_model(
|
|
1043
1041
|
self._get_db_tools(
|
|
1044
1042
|
user_id,
|
|
1045
1043
|
db,
|
|
@@ -1067,8 +1065,7 @@ class MemoryManager:
|
|
|
1067
1065
|
# Generate a response from the Model (includes running function calls)
|
|
1068
1066
|
response = await model_copy.aresponse(
|
|
1069
1067
|
messages=messages_for_model,
|
|
1070
|
-
tools=
|
|
1071
|
-
functions=self._functions_for_model,
|
|
1068
|
+
tools=_tools,
|
|
1072
1069
|
)
|
|
1073
1070
|
|
|
1074
1071
|
if response.tool_calls is not None and len(response.tool_calls) > 0:
|
|
@@ -1132,6 +1129,9 @@ class MemoryManager:
|
|
|
1132
1129
|
"""
|
|
1133
1130
|
from agno.db.base import UserMemory
|
|
1134
1131
|
|
|
1132
|
+
if memory == "":
|
|
1133
|
+
return "Can't update memory with empty string. Use the delete memory function if available."
|
|
1134
|
+
|
|
1135
1135
|
try:
|
|
1136
1136
|
db.upsert_user_memory(
|
|
1137
1137
|
UserMemory(
|
|
@@ -1251,6 +1251,9 @@ class MemoryManager:
|
|
|
1251
1251
|
"""
|
|
1252
1252
|
from agno.db.base import UserMemory
|
|
1253
1253
|
|
|
1254
|
+
if memory == "":
|
|
1255
|
+
return "Can't update memory with empty string. Use the delete memory function if available."
|
|
1256
|
+
|
|
1254
1257
|
try:
|
|
1255
1258
|
if isinstance(db, AsyncBaseDb):
|
|
1256
1259
|
await db.upsert_user_memory(
|
agno/models/anthropic/claude.py
CHANGED
|
@@ -86,6 +86,12 @@ class Claude(Model):
|
|
|
86
86
|
request_params: Optional[Dict[str, Any]] = None
|
|
87
87
|
mcp_servers: Optional[List[MCPServerConfiguration]] = None
|
|
88
88
|
|
|
89
|
+
# Skills configuration
|
|
90
|
+
skills: Optional[List[Dict[str, str]]] = (
|
|
91
|
+
None # e.g., [{"type": "anthropic", "skill_id": "pptx", "version": "latest"}]
|
|
92
|
+
)
|
|
93
|
+
betas: Optional[List[str]] = None # Enables specific experimental or newly released features.
|
|
94
|
+
|
|
89
95
|
# Client parameters
|
|
90
96
|
api_key: Optional[str] = None
|
|
91
97
|
default_headers: Optional[Dict[str, Any]] = None
|
|
@@ -101,6 +107,9 @@ class Claude(Model):
|
|
|
101
107
|
# Validate thinking support immediately at model creation
|
|
102
108
|
if self.thinking:
|
|
103
109
|
self._validate_thinking_support()
|
|
110
|
+
# Set up skills configuration if skills are enabled
|
|
111
|
+
if self.skills:
|
|
112
|
+
self._setup_skills_configuration()
|
|
104
113
|
|
|
105
114
|
def _get_client_params(self) -> Dict[str, Any]:
|
|
106
115
|
client_params: Dict[str, Any] = {}
|
|
@@ -159,6 +168,26 @@ class Claude(Model):
|
|
|
159
168
|
f"For more information, see: https://docs.anthropic.com/en/docs/about-claude/models/overview"
|
|
160
169
|
)
|
|
161
170
|
|
|
171
|
+
def _setup_skills_configuration(self) -> None:
|
|
172
|
+
"""
|
|
173
|
+
Set up configuration for Claude Agent Skills.
|
|
174
|
+
Automatically configures betas array with required values.
|
|
175
|
+
|
|
176
|
+
Skills enable document creation capabilities (PowerPoint, Excel, Word, PDF).
|
|
177
|
+
For more information, see: https://docs.claude.com/en/docs/agents-and-tools/agent-skills/quickstart
|
|
178
|
+
"""
|
|
179
|
+
# Required betas for skills
|
|
180
|
+
required_betas = ["code-execution-2025-08-25", "skills-2025-10-02"]
|
|
181
|
+
|
|
182
|
+
# Initialize or merge betas
|
|
183
|
+
if self.betas is None:
|
|
184
|
+
self.betas = required_betas
|
|
185
|
+
else:
|
|
186
|
+
# Add required betas if not present
|
|
187
|
+
for beta in required_betas:
|
|
188
|
+
if beta not in self.betas:
|
|
189
|
+
self.betas.append(beta)
|
|
190
|
+
|
|
162
191
|
def get_request_params(self) -> Dict[str, Any]:
|
|
163
192
|
"""
|
|
164
193
|
Generate keyword arguments for API requests.
|
|
@@ -184,6 +213,9 @@ class Claude(Model):
|
|
|
184
213
|
_request_params["mcp_servers"] = [
|
|
185
214
|
{k: v for k, v in asdict(server).items() if v is not None} for server in self.mcp_servers
|
|
186
215
|
]
|
|
216
|
+
if self.skills:
|
|
217
|
+
_request_params["betas"] = self.betas
|
|
218
|
+
_request_params["container"] = {"skills": self.skills}
|
|
187
219
|
if self.request_params:
|
|
188
220
|
_request_params.update(self.request_params)
|
|
189
221
|
|
|
@@ -213,6 +245,15 @@ class Claude(Model):
|
|
|
213
245
|
else:
|
|
214
246
|
request_kwargs["system"] = [{"text": system_message, "type": "text"}]
|
|
215
247
|
|
|
248
|
+
# Add code execution tool if skills are enabled
|
|
249
|
+
if self.skills:
|
|
250
|
+
code_execution_tool = {"type": "code_execution_20250825", "name": "code_execution"}
|
|
251
|
+
if tools:
|
|
252
|
+
# Add code_execution to existing tools, code execution is needed for generating and processing files
|
|
253
|
+
tools = tools + [code_execution_tool]
|
|
254
|
+
else:
|
|
255
|
+
tools = [code_execution_tool]
|
|
256
|
+
|
|
216
257
|
if tools:
|
|
217
258
|
request_kwargs["tools"] = format_tools_for_model(tools)
|
|
218
259
|
|
|
@@ -239,12 +280,12 @@ class Claude(Model):
|
|
|
239
280
|
chat_messages, system_message = format_messages(messages)
|
|
240
281
|
request_kwargs = self._prepare_request_kwargs(system_message, tools)
|
|
241
282
|
|
|
242
|
-
if self.mcp_servers is not None:
|
|
283
|
+
if self.mcp_servers is not None or self.skills is not None:
|
|
243
284
|
assistant_message.metrics.start_timer()
|
|
244
285
|
provider_response = self.get_client().beta.messages.create(
|
|
245
286
|
model=self.id,
|
|
246
287
|
messages=chat_messages, # type: ignore
|
|
247
|
-
**
|
|
288
|
+
**request_kwargs,
|
|
248
289
|
)
|
|
249
290
|
else:
|
|
250
291
|
assistant_message.metrics.start_timer()
|
|
@@ -306,7 +347,7 @@ class Claude(Model):
|
|
|
306
347
|
if run_response and run_response.metrics:
|
|
307
348
|
run_response.metrics.set_time_to_first_token()
|
|
308
349
|
|
|
309
|
-
if self.mcp_servers is not None:
|
|
350
|
+
if self.mcp_servers is not None or self.skills is not None:
|
|
310
351
|
assistant_message.metrics.start_timer()
|
|
311
352
|
with self.get_client().beta.messages.stream(
|
|
312
353
|
model=self.id,
|
|
@@ -361,12 +402,12 @@ class Claude(Model):
|
|
|
361
402
|
chat_messages, system_message = format_messages(messages)
|
|
362
403
|
request_kwargs = self._prepare_request_kwargs(system_message, tools)
|
|
363
404
|
|
|
364
|
-
if self.mcp_servers is not None:
|
|
405
|
+
if self.mcp_servers is not None or self.skills is not None:
|
|
365
406
|
assistant_message.metrics.start_timer()
|
|
366
407
|
provider_response = await self.get_async_client().beta.messages.create(
|
|
367
408
|
model=self.id,
|
|
368
409
|
messages=chat_messages, # type: ignore
|
|
369
|
-
**
|
|
410
|
+
**request_kwargs,
|
|
370
411
|
)
|
|
371
412
|
else:
|
|
372
413
|
assistant_message.metrics.start_timer()
|
|
@@ -425,7 +466,7 @@ class Claude(Model):
|
|
|
425
466
|
chat_messages, system_message = format_messages(messages)
|
|
426
467
|
request_kwargs = self._prepare_request_kwargs(system_message, tools)
|
|
427
468
|
|
|
428
|
-
if self.mcp_servers is not None:
|
|
469
|
+
if self.mcp_servers is not None or self.skills is not None:
|
|
429
470
|
assistant_message.metrics.start_timer()
|
|
430
471
|
async with self.get_async_client().beta.messages.stream(
|
|
431
472
|
model=self.id,
|
|
@@ -542,6 +583,22 @@ class Claude(Model):
|
|
|
542
583
|
if response.usage is not None:
|
|
543
584
|
model_response.response_usage = self._get_metrics(response.usage)
|
|
544
585
|
|
|
586
|
+
# Extract file IDs if skills are enabled
|
|
587
|
+
if self.skills and response.content:
|
|
588
|
+
file_ids: List[str] = []
|
|
589
|
+
for block in response.content:
|
|
590
|
+
if block.type == "bash_code_execution_tool_result":
|
|
591
|
+
if hasattr(block, "content") and hasattr(block.content, "content"):
|
|
592
|
+
if isinstance(block.content.content, list):
|
|
593
|
+
for output_block in block.content.content:
|
|
594
|
+
if hasattr(output_block, "file_id"):
|
|
595
|
+
file_ids.append(output_block.file_id)
|
|
596
|
+
|
|
597
|
+
if file_ids:
|
|
598
|
+
if model_response.provider_data is None:
|
|
599
|
+
model_response.provider_data = {}
|
|
600
|
+
model_response.provider_data["file_ids"] = file_ids
|
|
601
|
+
|
|
545
602
|
return model_response
|
|
546
603
|
|
|
547
604
|
def _parse_provider_response_delta(
|