agno 2.2.1__py3-none-any.whl → 2.2.3__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 +735 -574
- 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/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +1999 -0
- 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 +3 -3
- agno/knowledge/reader/reader_factory.py +16 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/memory/manager.py +28 -25
- agno/models/anthropic/claude.py +63 -6
- agno/models/base.py +251 -32
- 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 +25 -20
- agno/os/utils.py +9 -2
- agno/run/agent.py +23 -30
- agno/run/base.py +17 -1
- agno/run/team.py +23 -29
- agno/run/workflow.py +17 -12
- agno/session/agent.py +3 -0
- agno/session/summary.py +4 -1
- agno/session/team.py +1 -1
- agno/team/team.py +599 -367
- 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/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-2.2.1.dist-info → agno-2.2.3.dist-info}/METADATA +28 -25
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/RECORD +66 -62
- 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.1.dist-info → agno-2.2.3.dist-info}/WHEEL +0 -0
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/top_level.txt +0 -0
|
@@ -7,7 +7,7 @@ from rich.markdown import Markdown
|
|
|
7
7
|
from rich.status import Status
|
|
8
8
|
from rich.text import Text
|
|
9
9
|
|
|
10
|
-
from agno.media import Audio, Image, Video
|
|
10
|
+
from agno.media import Audio, File, Image, Video
|
|
11
11
|
from agno.models.message import Message
|
|
12
12
|
from agno.run.workflow import (
|
|
13
13
|
ConditionExecutionCompletedEvent,
|
|
@@ -48,6 +48,7 @@ def print_response(
|
|
|
48
48
|
audio: Optional[List[Audio]] = None,
|
|
49
49
|
images: Optional[List[Image]] = None,
|
|
50
50
|
videos: Optional[List[Video]] = None,
|
|
51
|
+
files: Optional[List[File]] = None,
|
|
51
52
|
markdown: bool = True,
|
|
52
53
|
show_time: bool = True,
|
|
53
54
|
show_step_details: bool = True,
|
|
@@ -76,6 +77,8 @@ def print_response(
|
|
|
76
77
|
media_info.append(f"Images: {len(images)}")
|
|
77
78
|
if videos:
|
|
78
79
|
media_info.append(f"Videos: {len(videos)}")
|
|
80
|
+
if files:
|
|
81
|
+
media_info.append(f"Files: {len(files)}")
|
|
79
82
|
|
|
80
83
|
workflow_info = f"""**Workflow:** {workflow.name}"""
|
|
81
84
|
if workflow.description:
|
|
@@ -126,6 +129,7 @@ def print_response(
|
|
|
126
129
|
audio=audio,
|
|
127
130
|
images=images,
|
|
128
131
|
videos=videos,
|
|
132
|
+
files=files,
|
|
129
133
|
**kwargs,
|
|
130
134
|
) # type: ignore
|
|
131
135
|
|
|
@@ -186,6 +190,7 @@ def print_response_stream(
|
|
|
186
190
|
audio: Optional[List[Audio]] = None,
|
|
187
191
|
images: Optional[List[Image]] = None,
|
|
188
192
|
videos: Optional[List[Video]] = None,
|
|
193
|
+
files: Optional[List[File]] = None,
|
|
189
194
|
stream_events: bool = False,
|
|
190
195
|
stream_intermediate_steps: bool = False,
|
|
191
196
|
markdown: bool = True,
|
|
@@ -210,6 +215,8 @@ def print_response_stream(
|
|
|
210
215
|
media_info.append(f"Images: {len(images)}")
|
|
211
216
|
if videos:
|
|
212
217
|
media_info.append(f"Videos: {len(videos)}")
|
|
218
|
+
if files:
|
|
219
|
+
media_info.append(f"Files: {len(files)}")
|
|
213
220
|
|
|
214
221
|
workflow_info = f"""**Workflow:** {workflow.name}"""
|
|
215
222
|
if workflow.description:
|
|
@@ -314,6 +321,7 @@ def print_response_stream(
|
|
|
314
321
|
audio=audio,
|
|
315
322
|
images=images,
|
|
316
323
|
videos=videos,
|
|
324
|
+
files=files,
|
|
317
325
|
stream=True,
|
|
318
326
|
stream_events=stream_events,
|
|
319
327
|
**kwargs,
|
|
@@ -832,6 +840,7 @@ async def aprint_response(
|
|
|
832
840
|
audio: Optional[List[Audio]] = None,
|
|
833
841
|
images: Optional[List[Image]] = None,
|
|
834
842
|
videos: Optional[List[Video]] = None,
|
|
843
|
+
files: Optional[List[File]] = None,
|
|
835
844
|
markdown: bool = True,
|
|
836
845
|
show_time: bool = True,
|
|
837
846
|
show_step_details: bool = True,
|
|
@@ -860,6 +869,8 @@ async def aprint_response(
|
|
|
860
869
|
media_info.append(f"Images: {len(images)}")
|
|
861
870
|
if videos:
|
|
862
871
|
media_info.append(f"Videos: {len(videos)}")
|
|
872
|
+
if files:
|
|
873
|
+
media_info.append(f"Files: {len(files)}")
|
|
863
874
|
|
|
864
875
|
workflow_info = f"""**Workflow:** {workflow.name}"""
|
|
865
876
|
if workflow.description:
|
|
@@ -910,6 +921,7 @@ async def aprint_response(
|
|
|
910
921
|
audio=audio,
|
|
911
922
|
images=images,
|
|
912
923
|
videos=videos,
|
|
924
|
+
files=files,
|
|
913
925
|
**kwargs,
|
|
914
926
|
) # type: ignore
|
|
915
927
|
|
|
@@ -970,6 +982,7 @@ async def aprint_response_stream(
|
|
|
970
982
|
audio: Optional[List[Audio]] = None,
|
|
971
983
|
images: Optional[List[Image]] = None,
|
|
972
984
|
videos: Optional[List[Video]] = None,
|
|
985
|
+
files: Optional[List[File]] = None,
|
|
973
986
|
stream_events: bool = False,
|
|
974
987
|
stream_intermediate_steps: bool = False,
|
|
975
988
|
markdown: bool = True,
|
|
@@ -994,6 +1007,8 @@ async def aprint_response_stream(
|
|
|
994
1007
|
media_info.append(f"Images: {len(images)}")
|
|
995
1008
|
if videos:
|
|
996
1009
|
media_info.append(f"Videos: {len(videos)}")
|
|
1010
|
+
if files:
|
|
1011
|
+
media_info.append(f"Files: {len(files)}")
|
|
997
1012
|
|
|
998
1013
|
workflow_info = f"""**Workflow:** {workflow.name}"""
|
|
999
1014
|
if workflow.description:
|
|
@@ -1098,6 +1113,7 @@ async def aprint_response_stream(
|
|
|
1098
1113
|
audio=audio,
|
|
1099
1114
|
images=images,
|
|
1100
1115
|
videos=videos,
|
|
1116
|
+
files=files,
|
|
1101
1117
|
stream=True,
|
|
1102
1118
|
stream_events=stream_events,
|
|
1103
1119
|
**kwargs,
|
agno/utils/team.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Optional, Union
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
2
2
|
|
|
3
3
|
from agno.agent import Agent
|
|
4
|
+
from agno.media import Audio, File, Image, Video
|
|
5
|
+
from agno.run.agent import RunOutput
|
|
6
|
+
from agno.run.team import TeamRunOutput
|
|
7
|
+
from agno.utils.log import log_debug
|
|
4
8
|
from agno.utils.string import is_valid_uuid, url_safe_string
|
|
5
9
|
|
|
6
10
|
if TYPE_CHECKING:
|
|
@@ -49,3 +53,87 @@ def get_member_id(member: Union[Agent, "Team"]) -> str:
|
|
|
49
53
|
else:
|
|
50
54
|
url_safe_member_id = None
|
|
51
55
|
return url_safe_member_id
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def add_interaction_to_team_run_context(
|
|
59
|
+
team_run_context: Dict[str, Any],
|
|
60
|
+
member_name: str,
|
|
61
|
+
task: str,
|
|
62
|
+
run_response: Union[RunOutput, TeamRunOutput],
|
|
63
|
+
) -> None:
|
|
64
|
+
if "member_responses" not in team_run_context:
|
|
65
|
+
team_run_context["member_responses"] = []
|
|
66
|
+
team_run_context["member_responses"].append(
|
|
67
|
+
{
|
|
68
|
+
"member_name": member_name,
|
|
69
|
+
"task": task,
|
|
70
|
+
"run_response": run_response,
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
log_debug(f"Updated team run context with member name: {member_name}")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_team_member_interactions_str(team_run_context: Dict[str, Any]) -> str:
|
|
77
|
+
if not team_run_context:
|
|
78
|
+
return ""
|
|
79
|
+
team_member_interactions_str = ""
|
|
80
|
+
if "member_responses" in team_run_context:
|
|
81
|
+
team_member_interactions_str += "<member_interaction_context>\nSee below interactions wit other team members.\n"
|
|
82
|
+
|
|
83
|
+
for interaction in team_run_context["member_responses"]:
|
|
84
|
+
response_dict = interaction["run_response"].to_dict()
|
|
85
|
+
response_content = (
|
|
86
|
+
response_dict.get("content")
|
|
87
|
+
or ",".join([tool.get("content", "") for tool in response_dict.get("tools", [])])
|
|
88
|
+
or ""
|
|
89
|
+
)
|
|
90
|
+
team_member_interactions_str += f"Member: {interaction['member_name']}\n"
|
|
91
|
+
team_member_interactions_str += f"Task: {interaction['task']}\n"
|
|
92
|
+
team_member_interactions_str += f"Response: {response_content}\n"
|
|
93
|
+
team_member_interactions_str += "\n"
|
|
94
|
+
team_member_interactions_str += "</member_interaction_context>\n"
|
|
95
|
+
return team_member_interactions_str
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_team_run_context_images(team_run_context: Dict[str, Any]) -> List[Image]:
|
|
99
|
+
if not team_run_context:
|
|
100
|
+
return []
|
|
101
|
+
images = []
|
|
102
|
+
if "member_responses" in team_run_context:
|
|
103
|
+
for interaction in team_run_context["member_responses"]:
|
|
104
|
+
if interaction["run_response"].images:
|
|
105
|
+
images.extend(interaction["run_response"].images)
|
|
106
|
+
return images
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def get_team_run_context_videos(team_run_context: Dict[str, Any]) -> List[Video]:
|
|
110
|
+
if not team_run_context:
|
|
111
|
+
return []
|
|
112
|
+
videos = []
|
|
113
|
+
if "member_responses" in team_run_context:
|
|
114
|
+
for interaction in team_run_context["member_responses"]:
|
|
115
|
+
if interaction["run_response"].videos:
|
|
116
|
+
videos.extend(interaction["run_response"].videos)
|
|
117
|
+
return videos
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def get_team_run_context_audio(team_run_context: Dict[str, Any]) -> List[Audio]:
|
|
121
|
+
if not team_run_context:
|
|
122
|
+
return []
|
|
123
|
+
audio = []
|
|
124
|
+
if "member_responses" in team_run_context:
|
|
125
|
+
for interaction in team_run_context["member_responses"]:
|
|
126
|
+
if interaction["run_response"].audio:
|
|
127
|
+
audio.extend(interaction["run_response"].audio)
|
|
128
|
+
return audio
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_team_run_context_files(team_run_context: Dict[str, Any]) -> List[File]:
|
|
132
|
+
if not team_run_context:
|
|
133
|
+
return []
|
|
134
|
+
files = []
|
|
135
|
+
if "member_responses" in team_run_context:
|
|
136
|
+
for interaction in team_run_context["member_responses"]:
|
|
137
|
+
if interaction["run_response"].files:
|
|
138
|
+
files.extend(interaction["run_response"].files)
|
|
139
|
+
return files
|
agno/workflow/step.py
CHANGED
|
@@ -382,7 +382,6 @@ class Step:
|
|
|
382
382
|
"""Enrich event with step and workflow context information"""
|
|
383
383
|
if workflow_run_response is None:
|
|
384
384
|
return event
|
|
385
|
-
|
|
386
385
|
if hasattr(event, "workflow_id"):
|
|
387
386
|
event.workflow_id = workflow_run_response.workflow_id
|
|
388
387
|
if hasattr(event, "workflow_run_id"):
|
agno/workflow/types.py
CHANGED
|
@@ -10,6 +10,12 @@ from agno.media import Audio, File, Image, Video
|
|
|
10
10
|
from agno.models.metrics import Metrics
|
|
11
11
|
from agno.session.workflow import WorkflowSession
|
|
12
12
|
from agno.utils.log import log_warning
|
|
13
|
+
from agno.utils.media import (
|
|
14
|
+
reconstruct_audio_list,
|
|
15
|
+
reconstruct_files,
|
|
16
|
+
reconstruct_images,
|
|
17
|
+
reconstruct_videos,
|
|
18
|
+
)
|
|
13
19
|
from agno.utils.serialize import json_serializer
|
|
14
20
|
|
|
15
21
|
|
|
@@ -308,21 +314,10 @@ class StepOutput:
|
|
|
308
314
|
def from_dict(cls, data: Dict[str, Any]) -> "StepOutput":
|
|
309
315
|
"""Create StepOutput from dictionary"""
|
|
310
316
|
# Reconstruct media artifacts
|
|
311
|
-
images = data.get("images")
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
videos = data.get("videos")
|
|
316
|
-
if videos:
|
|
317
|
-
videos = [Video.model_validate(vid) for vid in videos]
|
|
318
|
-
|
|
319
|
-
audio = data.get("audio")
|
|
320
|
-
if audio:
|
|
321
|
-
audio = [Audio.model_validate(aud) for aud in audio]
|
|
322
|
-
|
|
323
|
-
files = data.get("files")
|
|
324
|
-
if files:
|
|
325
|
-
files = [File.model_validate(file) for file in files]
|
|
317
|
+
images = reconstruct_images(data.get("images"))
|
|
318
|
+
videos = reconstruct_videos(data.get("videos"))
|
|
319
|
+
audio = reconstruct_audio_list(data.get("audio"))
|
|
320
|
+
files = reconstruct_files(data.get("files"))
|
|
326
321
|
|
|
327
322
|
metrics_data = data.get("metrics")
|
|
328
323
|
metrics = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agno
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
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
|
|
@@ -135,6 +135,8 @@ Provides-Extra: fal
|
|
|
135
135
|
Requires-Dist: fal_client; extra == "fal"
|
|
136
136
|
Provides-Extra: firecrawl
|
|
137
137
|
Requires-Dist: firecrawl-py; extra == "firecrawl"
|
|
138
|
+
Provides-Extra: tavily
|
|
139
|
+
Requires-Dist: tavily-python; extra == "tavily"
|
|
138
140
|
Provides-Extra: crawl4ai
|
|
139
141
|
Requires-Dist: crawl4ai; extra == "crawl4ai"
|
|
140
142
|
Provides-Extra: github
|
|
@@ -296,6 +298,7 @@ Requires-Dist: agno[duckdb]; extra == "tools"
|
|
|
296
298
|
Requires-Dist: agno[newspaper]; extra == "tools"
|
|
297
299
|
Requires-Dist: agno[youtube]; extra == "tools"
|
|
298
300
|
Requires-Dist: agno[firecrawl]; extra == "tools"
|
|
301
|
+
Requires-Dist: agno[tavily]; extra == "tools"
|
|
299
302
|
Requires-Dist: agno[crawl4ai]; extra == "tools"
|
|
300
303
|
Requires-Dist: agno[github]; extra == "tools"
|
|
301
304
|
Requires-Dist: agno[gmail]; extra == "tools"
|
|
@@ -449,6 +452,30 @@ if __name__ == "__main__":
|
|
|
449
452
|
agent_os.serve(app="agno_agent:app", reload=True)
|
|
450
453
|
```
|
|
451
454
|
|
|
455
|
+
## AgentOS - Production Runtime for Multi-Agent Systems
|
|
456
|
+
|
|
457
|
+
AgentOS is Agno's high-performance runtime for serving multi-agent systems in production. Key features include:
|
|
458
|
+
|
|
459
|
+
1. **Pre-built FastAPI Runtime**: AgentOS ships with a ready-to-use FastAPI app for orchestrating your agents, teams, and workflows. This provides a major head start when building an AI product.
|
|
460
|
+
|
|
461
|
+
2. **Integrated Control Plane**: The [AgentOS UI](https://os.agno.com) connects directly to your runtime, letting you test, monitor, and manage your system in real time. This gives you unmatched visibility and control over your system.
|
|
462
|
+
|
|
463
|
+
3. **Private by Design**: AgentOS runs entirely in your cloud, ensuring complete data privacy. No data ever leaves your system. This is ideal for security-conscious enterprises.
|
|
464
|
+
|
|
465
|
+
Here's what the [AgentOS UI](https://os.agno.com) looks like in action:
|
|
466
|
+
|
|
467
|
+
https://github.com/user-attachments/assets/feb23db8-15cc-4e88-be7c-01a21a03ebf6
|
|
468
|
+
|
|
469
|
+
## The Complete Agentic Solution
|
|
470
|
+
|
|
471
|
+
For companies building agents, Agno provides the complete agentic solution:
|
|
472
|
+
|
|
473
|
+
- The fastest framework for building agents, multi-agent teams and agentic workflows.
|
|
474
|
+
- A ready-to-use FastAPI app that gets you building AI products on day one.
|
|
475
|
+
- A control plane for testing, monitoring and managing your system.
|
|
476
|
+
|
|
477
|
+
Agno brings a novel architecture that no other framework provides, your AgentOS runs securely in your cloud, and the control plane connects directly to it from your browser. You don't need to send data to any external services or pay retention costs, you get complete privacy and control.
|
|
478
|
+
|
|
452
479
|
## Designed for Agent Engineering
|
|
453
480
|
|
|
454
481
|
Agno is a remarkably feature-rich framework, purpose-built for large-scale multi-agent deployments.
|
|
@@ -477,30 +504,6 @@ Agno is a remarkably feature-rich framework, purpose-built for large-scale multi
|
|
|
477
504
|
|
|
478
505
|
Every part of Agno is built for real-world deployment — where developer experience meets production performance.
|
|
479
506
|
|
|
480
|
-
## AgentOS - Production Runtime for Multi-Agent Systems
|
|
481
|
-
|
|
482
|
-
AgentOS is Agno's high-performance runtime for serving multi-agent systems in production. Key features include:
|
|
483
|
-
|
|
484
|
-
1. **Pre-built FastAPI Runtime**: AgentOS ships with a ready-to-use FastAPI app for orchestrating your agents, teams, and workflows. This provides a major head start when building an AI product.
|
|
485
|
-
|
|
486
|
-
2. **Integrated Control Plane**: The [AgentOS UI](https://os.agno.com) connects directly to your runtime, letting you test, monitor, and manage your system in real time. This gives you unmatched visibility and control over your system.
|
|
487
|
-
|
|
488
|
-
3. **Private by Design**: AgentOS runs entirely in your cloud, ensuring complete data privacy. No data ever leaves your system. This is ideal for security-conscious enterprises.
|
|
489
|
-
|
|
490
|
-
Here's what the [AgentOS UI](https://os.agno.com) looks like in action:
|
|
491
|
-
|
|
492
|
-
https://github.com/user-attachments/assets/feb23db8-15cc-4e88-be7c-01a21a03ebf6
|
|
493
|
-
|
|
494
|
-
## The Complete Agentic Solution
|
|
495
|
-
|
|
496
|
-
For companies building agents, Agno provides the complete agentic solution:
|
|
497
|
-
|
|
498
|
-
- The fastest framework for building agents, multi-agent teams and agentic workflows.
|
|
499
|
-
- A ready-to-use FastAPI app that gets you building AI products on day one.
|
|
500
|
-
- A control plane for testing, monitoring and managing your system.
|
|
501
|
-
|
|
502
|
-
Agno brings a novel architecture that no other framework provides, your AgentOS runs securely in your cloud, and the control plane connects directly to it from your browser. You don't need to send data to any external services or pay retention costs, you get complete privacy and control.
|
|
503
|
-
|
|
504
507
|
## Setup Your Coding Agent to Use Agno
|
|
505
508
|
|
|
506
509
|
For LLMs and AI assistants to understand and navigate Agno's documentation, we provide an [llms.txt](https://docs.agno.com/llms.txt) or [llms-full.txt](https://docs.agno.com/llms-full.txt) file. This file is built for AI systems to efficiently parse and reference our documentation.
|