agno 2.2.1__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.
Files changed (67) hide show
  1. agno/agent/agent.py +735 -574
  2. agno/culture/manager.py +22 -24
  3. agno/db/async_postgres/__init__.py +1 -1
  4. agno/db/dynamo/dynamo.py +0 -2
  5. agno/db/firestore/firestore.py +0 -2
  6. agno/db/gcs_json/gcs_json_db.py +0 -4
  7. agno/db/gcs_json/utils.py +0 -24
  8. agno/db/in_memory/in_memory_db.py +0 -3
  9. agno/db/json/json_db.py +4 -10
  10. agno/db/json/utils.py +0 -24
  11. agno/db/mongo/mongo.py +0 -2
  12. agno/db/mysql/mysql.py +0 -3
  13. agno/db/postgres/__init__.py +1 -1
  14. agno/db/{async_postgres → postgres}/async_postgres.py +19 -22
  15. agno/db/postgres/postgres.py +7 -10
  16. agno/db/postgres/utils.py +106 -2
  17. agno/db/redis/redis.py +0 -2
  18. agno/db/singlestore/singlestore.py +0 -3
  19. agno/db/sqlite/__init__.py +2 -1
  20. agno/db/sqlite/async_sqlite.py +2269 -0
  21. agno/db/sqlite/sqlite.py +0 -2
  22. agno/db/sqlite/utils.py +96 -0
  23. agno/db/surrealdb/surrealdb.py +0 -6
  24. agno/knowledge/knowledge.py +3 -3
  25. agno/knowledge/reader/reader_factory.py +16 -0
  26. agno/knowledge/reader/tavily_reader.py +194 -0
  27. agno/memory/manager.py +28 -25
  28. agno/models/anthropic/claude.py +63 -6
  29. agno/models/base.py +251 -32
  30. agno/models/response.py +69 -0
  31. agno/os/router.py +7 -5
  32. agno/os/routers/memory/memory.py +2 -1
  33. agno/os/routers/memory/schemas.py +5 -2
  34. agno/os/schema.py +26 -20
  35. agno/os/utils.py +9 -2
  36. agno/run/agent.py +23 -30
  37. agno/run/base.py +17 -1
  38. agno/run/team.py +23 -29
  39. agno/run/workflow.py +17 -12
  40. agno/session/agent.py +3 -0
  41. agno/session/summary.py +4 -1
  42. agno/session/team.py +1 -1
  43. agno/team/team.py +591 -365
  44. agno/tools/dalle.py +2 -4
  45. agno/tools/eleven_labs.py +23 -25
  46. agno/tools/function.py +40 -0
  47. agno/tools/mcp/__init__.py +10 -0
  48. agno/tools/mcp/mcp.py +324 -0
  49. agno/tools/mcp/multi_mcp.py +347 -0
  50. agno/tools/mcp/params.py +24 -0
  51. agno/tools/slack.py +18 -3
  52. agno/tools/tavily.py +146 -0
  53. agno/utils/agent.py +366 -1
  54. agno/utils/mcp.py +92 -2
  55. agno/utils/media.py +166 -1
  56. agno/utils/print_response/workflow.py +17 -1
  57. agno/utils/team.py +89 -1
  58. agno/workflow/step.py +0 -1
  59. agno/workflow/types.py +10 -15
  60. {agno-2.2.1.dist-info → agno-2.2.2.dist-info}/METADATA +28 -25
  61. {agno-2.2.1.dist-info → agno-2.2.2.dist-info}/RECORD +64 -61
  62. agno/db/async_postgres/schemas.py +0 -139
  63. agno/db/async_postgres/utils.py +0 -347
  64. agno/tools/mcp.py +0 -679
  65. {agno-2.2.1.dist-info → agno-2.2.2.dist-info}/WHEEL +0 -0
  66. {agno-2.2.1.dist-info → agno-2.2.2.dist-info}/licenses/LICENSE +0 -0
  67. {agno-2.2.1.dist-info → agno-2.2.2.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
- if images:
313
- images = [Image.model_validate(img) for img in images]
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.1
3
+ Version: 2.2.2
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.