agno 2.0.1__py3-none-any.whl → 2.3.0__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 (314) hide show
  1. agno/agent/agent.py +6015 -2823
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/culture/__init__.py +3 -0
  5. agno/culture/manager.py +956 -0
  6. agno/db/async_postgres/__init__.py +3 -0
  7. agno/db/base.py +385 -6
  8. agno/db/dynamo/dynamo.py +388 -81
  9. agno/db/dynamo/schemas.py +47 -10
  10. agno/db/dynamo/utils.py +63 -4
  11. agno/db/firestore/firestore.py +435 -64
  12. agno/db/firestore/schemas.py +11 -0
  13. agno/db/firestore/utils.py +102 -4
  14. agno/db/gcs_json/gcs_json_db.py +384 -42
  15. agno/db/gcs_json/utils.py +60 -26
  16. agno/db/in_memory/in_memory_db.py +351 -66
  17. agno/db/in_memory/utils.py +60 -2
  18. agno/db/json/json_db.py +339 -48
  19. agno/db/json/utils.py +60 -26
  20. agno/db/migrations/manager.py +199 -0
  21. agno/db/migrations/v1_to_v2.py +510 -37
  22. agno/db/migrations/versions/__init__.py +0 -0
  23. agno/db/migrations/versions/v2_3_0.py +938 -0
  24. agno/db/mongo/__init__.py +15 -1
  25. agno/db/mongo/async_mongo.py +2036 -0
  26. agno/db/mongo/mongo.py +653 -76
  27. agno/db/mongo/schemas.py +13 -0
  28. agno/db/mongo/utils.py +80 -8
  29. agno/db/mysql/mysql.py +687 -25
  30. agno/db/mysql/schemas.py +61 -37
  31. agno/db/mysql/utils.py +60 -2
  32. agno/db/postgres/__init__.py +2 -1
  33. agno/db/postgres/async_postgres.py +2001 -0
  34. agno/db/postgres/postgres.py +676 -57
  35. agno/db/postgres/schemas.py +43 -18
  36. agno/db/postgres/utils.py +164 -2
  37. agno/db/redis/redis.py +344 -38
  38. agno/db/redis/schemas.py +18 -0
  39. agno/db/redis/utils.py +60 -2
  40. agno/db/schemas/__init__.py +2 -1
  41. agno/db/schemas/culture.py +120 -0
  42. agno/db/schemas/memory.py +13 -0
  43. agno/db/singlestore/schemas.py +26 -1
  44. agno/db/singlestore/singlestore.py +687 -53
  45. agno/db/singlestore/utils.py +60 -2
  46. agno/db/sqlite/__init__.py +2 -1
  47. agno/db/sqlite/async_sqlite.py +2371 -0
  48. agno/db/sqlite/schemas.py +24 -0
  49. agno/db/sqlite/sqlite.py +774 -85
  50. agno/db/sqlite/utils.py +168 -5
  51. agno/db/surrealdb/__init__.py +3 -0
  52. agno/db/surrealdb/metrics.py +292 -0
  53. agno/db/surrealdb/models.py +309 -0
  54. agno/db/surrealdb/queries.py +71 -0
  55. agno/db/surrealdb/surrealdb.py +1361 -0
  56. agno/db/surrealdb/utils.py +147 -0
  57. agno/db/utils.py +50 -22
  58. agno/eval/accuracy.py +50 -43
  59. agno/eval/performance.py +6 -3
  60. agno/eval/reliability.py +6 -3
  61. agno/eval/utils.py +33 -16
  62. agno/exceptions.py +68 -1
  63. agno/filters.py +354 -0
  64. agno/guardrails/__init__.py +6 -0
  65. agno/guardrails/base.py +19 -0
  66. agno/guardrails/openai.py +144 -0
  67. agno/guardrails/pii.py +94 -0
  68. agno/guardrails/prompt_injection.py +52 -0
  69. agno/integrations/discord/client.py +1 -0
  70. agno/knowledge/chunking/agentic.py +13 -10
  71. agno/knowledge/chunking/fixed.py +1 -1
  72. agno/knowledge/chunking/semantic.py +40 -8
  73. agno/knowledge/chunking/strategy.py +59 -15
  74. agno/knowledge/embedder/aws_bedrock.py +9 -4
  75. agno/knowledge/embedder/azure_openai.py +54 -0
  76. agno/knowledge/embedder/base.py +2 -0
  77. agno/knowledge/embedder/cohere.py +184 -5
  78. agno/knowledge/embedder/fastembed.py +1 -1
  79. agno/knowledge/embedder/google.py +79 -1
  80. agno/knowledge/embedder/huggingface.py +9 -4
  81. agno/knowledge/embedder/jina.py +63 -0
  82. agno/knowledge/embedder/mistral.py +78 -11
  83. agno/knowledge/embedder/nebius.py +1 -1
  84. agno/knowledge/embedder/ollama.py +13 -0
  85. agno/knowledge/embedder/openai.py +37 -65
  86. agno/knowledge/embedder/sentence_transformer.py +8 -4
  87. agno/knowledge/embedder/vllm.py +262 -0
  88. agno/knowledge/embedder/voyageai.py +69 -16
  89. agno/knowledge/knowledge.py +594 -186
  90. agno/knowledge/reader/base.py +9 -2
  91. agno/knowledge/reader/csv_reader.py +8 -10
  92. agno/knowledge/reader/docx_reader.py +5 -6
  93. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  94. agno/knowledge/reader/json_reader.py +6 -5
  95. agno/knowledge/reader/markdown_reader.py +13 -13
  96. agno/knowledge/reader/pdf_reader.py +43 -68
  97. agno/knowledge/reader/pptx_reader.py +101 -0
  98. agno/knowledge/reader/reader_factory.py +51 -6
  99. agno/knowledge/reader/s3_reader.py +3 -15
  100. agno/knowledge/reader/tavily_reader.py +194 -0
  101. agno/knowledge/reader/text_reader.py +13 -13
  102. agno/knowledge/reader/web_search_reader.py +2 -43
  103. agno/knowledge/reader/website_reader.py +43 -25
  104. agno/knowledge/reranker/__init__.py +2 -8
  105. agno/knowledge/types.py +9 -0
  106. agno/knowledge/utils.py +20 -0
  107. agno/media.py +72 -0
  108. agno/memory/manager.py +336 -82
  109. agno/models/aimlapi/aimlapi.py +2 -2
  110. agno/models/anthropic/claude.py +183 -37
  111. agno/models/aws/bedrock.py +52 -112
  112. agno/models/aws/claude.py +33 -1
  113. agno/models/azure/ai_foundry.py +33 -15
  114. agno/models/azure/openai_chat.py +25 -8
  115. agno/models/base.py +999 -519
  116. agno/models/cerebras/cerebras.py +19 -13
  117. agno/models/cerebras/cerebras_openai.py +8 -5
  118. agno/models/cohere/chat.py +27 -1
  119. agno/models/cometapi/__init__.py +5 -0
  120. agno/models/cometapi/cometapi.py +57 -0
  121. agno/models/dashscope/dashscope.py +1 -0
  122. agno/models/deepinfra/deepinfra.py +2 -2
  123. agno/models/deepseek/deepseek.py +2 -2
  124. agno/models/fireworks/fireworks.py +2 -2
  125. agno/models/google/gemini.py +103 -31
  126. agno/models/groq/groq.py +28 -11
  127. agno/models/huggingface/huggingface.py +2 -1
  128. agno/models/internlm/internlm.py +2 -2
  129. agno/models/langdb/langdb.py +4 -4
  130. agno/models/litellm/chat.py +18 -1
  131. agno/models/litellm/litellm_openai.py +2 -2
  132. agno/models/llama_cpp/__init__.py +5 -0
  133. agno/models/llama_cpp/llama_cpp.py +22 -0
  134. agno/models/message.py +139 -0
  135. agno/models/meta/llama.py +27 -10
  136. agno/models/meta/llama_openai.py +5 -17
  137. agno/models/nebius/nebius.py +6 -6
  138. agno/models/nexus/__init__.py +3 -0
  139. agno/models/nexus/nexus.py +22 -0
  140. agno/models/nvidia/nvidia.py +2 -2
  141. agno/models/ollama/chat.py +59 -5
  142. agno/models/openai/chat.py +69 -29
  143. agno/models/openai/responses.py +103 -106
  144. agno/models/openrouter/openrouter.py +41 -3
  145. agno/models/perplexity/perplexity.py +4 -5
  146. agno/models/portkey/portkey.py +3 -3
  147. agno/models/requesty/__init__.py +5 -0
  148. agno/models/requesty/requesty.py +52 -0
  149. agno/models/response.py +77 -1
  150. agno/models/sambanova/sambanova.py +2 -2
  151. agno/models/siliconflow/__init__.py +5 -0
  152. agno/models/siliconflow/siliconflow.py +25 -0
  153. agno/models/together/together.py +2 -2
  154. agno/models/utils.py +254 -8
  155. agno/models/vercel/v0.py +2 -2
  156. agno/models/vertexai/__init__.py +0 -0
  157. agno/models/vertexai/claude.py +96 -0
  158. agno/models/vllm/vllm.py +1 -0
  159. agno/models/xai/xai.py +3 -2
  160. agno/os/app.py +543 -178
  161. agno/os/auth.py +24 -14
  162. agno/os/config.py +1 -0
  163. agno/os/interfaces/__init__.py +1 -0
  164. agno/os/interfaces/a2a/__init__.py +3 -0
  165. agno/os/interfaces/a2a/a2a.py +42 -0
  166. agno/os/interfaces/a2a/router.py +250 -0
  167. agno/os/interfaces/a2a/utils.py +924 -0
  168. agno/os/interfaces/agui/agui.py +23 -7
  169. agno/os/interfaces/agui/router.py +27 -3
  170. agno/os/interfaces/agui/utils.py +242 -142
  171. agno/os/interfaces/base.py +6 -2
  172. agno/os/interfaces/slack/router.py +81 -23
  173. agno/os/interfaces/slack/slack.py +29 -14
  174. agno/os/interfaces/whatsapp/router.py +11 -4
  175. agno/os/interfaces/whatsapp/whatsapp.py +14 -7
  176. agno/os/mcp.py +111 -54
  177. agno/os/middleware/__init__.py +7 -0
  178. agno/os/middleware/jwt.py +233 -0
  179. agno/os/router.py +556 -139
  180. agno/os/routers/evals/evals.py +71 -34
  181. agno/os/routers/evals/schemas.py +31 -31
  182. agno/os/routers/evals/utils.py +6 -5
  183. agno/os/routers/health.py +31 -0
  184. agno/os/routers/home.py +52 -0
  185. agno/os/routers/knowledge/knowledge.py +185 -38
  186. agno/os/routers/knowledge/schemas.py +82 -22
  187. agno/os/routers/memory/memory.py +158 -53
  188. agno/os/routers/memory/schemas.py +20 -16
  189. agno/os/routers/metrics/metrics.py +20 -8
  190. agno/os/routers/metrics/schemas.py +16 -16
  191. agno/os/routers/session/session.py +499 -38
  192. agno/os/schema.py +308 -198
  193. agno/os/utils.py +401 -41
  194. agno/reasoning/anthropic.py +80 -0
  195. agno/reasoning/azure_ai_foundry.py +2 -2
  196. agno/reasoning/deepseek.py +2 -2
  197. agno/reasoning/default.py +3 -1
  198. agno/reasoning/gemini.py +73 -0
  199. agno/reasoning/groq.py +2 -2
  200. agno/reasoning/ollama.py +2 -2
  201. agno/reasoning/openai.py +7 -2
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +248 -94
  205. agno/run/base.py +44 -5
  206. agno/run/team.py +238 -97
  207. agno/run/workflow.py +144 -33
  208. agno/session/agent.py +105 -89
  209. agno/session/summary.py +65 -25
  210. agno/session/team.py +176 -96
  211. agno/session/workflow.py +406 -40
  212. agno/team/team.py +3854 -1610
  213. agno/tools/dalle.py +2 -4
  214. agno/tools/decorator.py +4 -2
  215. agno/tools/duckduckgo.py +15 -11
  216. agno/tools/e2b.py +14 -7
  217. agno/tools/eleven_labs.py +23 -25
  218. agno/tools/exa.py +21 -16
  219. agno/tools/file.py +153 -23
  220. agno/tools/file_generation.py +350 -0
  221. agno/tools/firecrawl.py +4 -4
  222. agno/tools/function.py +250 -30
  223. agno/tools/gmail.py +238 -14
  224. agno/tools/google_drive.py +270 -0
  225. agno/tools/googlecalendar.py +36 -8
  226. agno/tools/googlesheets.py +20 -5
  227. agno/tools/jira.py +20 -0
  228. agno/tools/knowledge.py +3 -3
  229. agno/tools/mcp/__init__.py +10 -0
  230. agno/tools/mcp/mcp.py +331 -0
  231. agno/tools/mcp/multi_mcp.py +347 -0
  232. agno/tools/mcp/params.py +24 -0
  233. agno/tools/mcp_toolbox.py +284 -0
  234. agno/tools/mem0.py +11 -17
  235. agno/tools/memori.py +1 -53
  236. agno/tools/memory.py +419 -0
  237. agno/tools/models/nebius.py +5 -5
  238. agno/tools/models_labs.py +20 -10
  239. agno/tools/notion.py +204 -0
  240. agno/tools/parallel.py +314 -0
  241. agno/tools/scrapegraph.py +58 -31
  242. agno/tools/searxng.py +2 -2
  243. agno/tools/serper.py +2 -2
  244. agno/tools/slack.py +18 -3
  245. agno/tools/spider.py +2 -2
  246. agno/tools/tavily.py +146 -0
  247. agno/tools/whatsapp.py +1 -1
  248. agno/tools/workflow.py +278 -0
  249. agno/tools/yfinance.py +12 -11
  250. agno/utils/agent.py +820 -0
  251. agno/utils/audio.py +27 -0
  252. agno/utils/common.py +90 -1
  253. agno/utils/events.py +217 -2
  254. agno/utils/gemini.py +180 -22
  255. agno/utils/hooks.py +57 -0
  256. agno/utils/http.py +111 -0
  257. agno/utils/knowledge.py +12 -5
  258. agno/utils/log.py +1 -0
  259. agno/utils/mcp.py +92 -2
  260. agno/utils/media.py +188 -10
  261. agno/utils/merge_dict.py +22 -1
  262. agno/utils/message.py +60 -0
  263. agno/utils/models/claude.py +40 -11
  264. agno/utils/print_response/agent.py +105 -21
  265. agno/utils/print_response/team.py +103 -38
  266. agno/utils/print_response/workflow.py +251 -34
  267. agno/utils/reasoning.py +22 -1
  268. agno/utils/serialize.py +32 -0
  269. agno/utils/streamlit.py +16 -10
  270. agno/utils/string.py +41 -0
  271. agno/utils/team.py +98 -9
  272. agno/utils/tools.py +1 -1
  273. agno/vectordb/base.py +23 -4
  274. agno/vectordb/cassandra/cassandra.py +65 -9
  275. agno/vectordb/chroma/chromadb.py +182 -38
  276. agno/vectordb/clickhouse/clickhousedb.py +64 -11
  277. agno/vectordb/couchbase/couchbase.py +105 -10
  278. agno/vectordb/lancedb/lance_db.py +124 -133
  279. agno/vectordb/langchaindb/langchaindb.py +25 -7
  280. agno/vectordb/lightrag/lightrag.py +17 -3
  281. agno/vectordb/llamaindex/__init__.py +3 -0
  282. agno/vectordb/llamaindex/llamaindexdb.py +46 -7
  283. agno/vectordb/milvus/milvus.py +126 -9
  284. agno/vectordb/mongodb/__init__.py +7 -1
  285. agno/vectordb/mongodb/mongodb.py +112 -7
  286. agno/vectordb/pgvector/pgvector.py +142 -21
  287. agno/vectordb/pineconedb/pineconedb.py +80 -8
  288. agno/vectordb/qdrant/qdrant.py +125 -39
  289. agno/vectordb/redis/__init__.py +9 -0
  290. agno/vectordb/redis/redisdb.py +694 -0
  291. agno/vectordb/singlestore/singlestore.py +111 -25
  292. agno/vectordb/surrealdb/surrealdb.py +31 -5
  293. agno/vectordb/upstashdb/upstashdb.py +76 -8
  294. agno/vectordb/weaviate/weaviate.py +86 -15
  295. agno/workflow/__init__.py +2 -0
  296. agno/workflow/agent.py +299 -0
  297. agno/workflow/condition.py +112 -18
  298. agno/workflow/loop.py +69 -10
  299. agno/workflow/parallel.py +266 -118
  300. agno/workflow/router.py +110 -17
  301. agno/workflow/step.py +638 -129
  302. agno/workflow/steps.py +65 -6
  303. agno/workflow/types.py +61 -23
  304. agno/workflow/workflow.py +2085 -272
  305. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/METADATA +182 -58
  306. agno-2.3.0.dist-info/RECORD +577 -0
  307. agno/knowledge/reader/url_reader.py +0 -128
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -610
  310. agno/utils/models/aws_claude.py +0 -170
  311. agno-2.0.1.dist-info/RECORD +0 -515
  312. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
  313. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
agno/utils/audio.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import os
3
+ import wave
3
4
 
4
5
  from agno.utils.log import log_info
5
6
 
@@ -20,3 +21,29 @@ def write_audio_to_file(audio, filename: str):
20
21
  with open(filename, "wb") as f:
21
22
  f.write(wav_bytes)
22
23
  log_info(f"Audio file saved to {filename}")
24
+
25
+
26
+ def write_wav_audio_to_file(
27
+ filename: str, pcm_data: bytes, channels: int = 1, rate: int = 24000, sample_width: int = 2
28
+ ):
29
+ """
30
+ Create a WAV file from raw PCM audio data.
31
+
32
+ Args:
33
+ filename: The filepath to save the WAV file to
34
+ pcm_data: Raw PCM audio data as bytes
35
+ channels: Number of audio channels (1 for mono, 2 for stereo)
36
+ rate: Sample rate in Hz (e.g., 24000, 44100, 48000)
37
+ sample_width: Sample width in bytes (1, 2, or 4)
38
+ """
39
+ # Create directory if it doesn't exist
40
+ if os.path.dirname(filename):
41
+ os.makedirs(os.path.dirname(filename), exist_ok=True)
42
+
43
+ with wave.open(filename, "wb") as wf:
44
+ wf.setnchannels(channels)
45
+ wf.setsampwidth(sample_width)
46
+ wf.setframerate(rate)
47
+ wf.writeframes(pcm_data)
48
+
49
+ log_info(f"WAV file saved to {filename}")
agno/utils/common.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from dataclasses import asdict
2
- from typing import Any, List, Optional, Type
2
+ from typing import Any, List, Optional, Set, Type, Union, get_type_hints
3
3
 
4
4
 
5
5
  def isinstanceany(obj: Any, class_list: List[Type]) -> bool:
@@ -41,3 +41,92 @@ def nested_model_dump(value):
41
41
  elif isinstance(value, list):
42
42
  return [nested_model_dump(item) for item in value]
43
43
  return value
44
+
45
+
46
+ def is_typed_dict(cls: Type[Any]) -> bool:
47
+ """Check if a class is a TypedDict"""
48
+ return (
49
+ hasattr(cls, "__annotations__")
50
+ and hasattr(cls, "__total__")
51
+ and hasattr(cls, "__required_keys__")
52
+ and hasattr(cls, "__optional_keys__")
53
+ )
54
+
55
+
56
+ def check_type_compatibility(value: Any, expected_type: Type) -> bool:
57
+ """Basic type compatibility checking."""
58
+ from typing import get_args, get_origin
59
+
60
+ # Handle None/Optional types
61
+ if value is None:
62
+ return (
63
+ type(None) in get_args(expected_type) if hasattr(expected_type, "__args__") else expected_type is type(None)
64
+ )
65
+
66
+ # Handle Union types (including Optional)
67
+ origin = get_origin(expected_type)
68
+ if origin is Union:
69
+ return any(check_type_compatibility(value, arg) for arg in get_args(expected_type))
70
+
71
+ # Handle List types
72
+ if origin is list or expected_type is list:
73
+ if not isinstance(value, list):
74
+ return False
75
+ if origin is list and get_args(expected_type):
76
+ element_type = get_args(expected_type)[0]
77
+ return all(check_type_compatibility(item, element_type) for item in value)
78
+ return True
79
+
80
+ if expected_type in (str, int, float, bool):
81
+ return isinstance(value, expected_type)
82
+
83
+ if expected_type is Any:
84
+ return True
85
+
86
+ try:
87
+ return isinstance(value, expected_type)
88
+ except TypeError:
89
+ return True
90
+
91
+
92
+ def validate_typed_dict(data: dict, schema_cls) -> dict:
93
+ """Validate input data against a TypedDict schema."""
94
+ if not isinstance(data, dict):
95
+ raise ValueError(f"Expected dict for TypedDict {schema_cls.__name__}, got {type(data)}")
96
+
97
+ # Get type hints from the TypedDict
98
+ try:
99
+ type_hints = get_type_hints(schema_cls)
100
+ except Exception as e:
101
+ raise ValueError(f"Could not get type hints for TypedDict {schema_cls.__name__}: {e}")
102
+
103
+ # Get required and optional keys
104
+ required_keys: Set[str] = getattr(schema_cls, "__required_keys__", set())
105
+ optional_keys: Set[str] = getattr(schema_cls, "__optional_keys__", set())
106
+ all_keys = required_keys | optional_keys
107
+
108
+ # Check for missing required fields
109
+ missing_required = required_keys - set(data.keys())
110
+ if missing_required:
111
+ raise ValueError(f"Missing required fields in TypedDict {schema_cls.__name__}: {missing_required}")
112
+
113
+ # Check for unexpected fields
114
+ unexpected_fields = set(data.keys()) - all_keys
115
+ if unexpected_fields:
116
+ raise ValueError(f"Unexpected fields in TypedDict {schema_cls.__name__}: {unexpected_fields}")
117
+
118
+ # Basic type checking for provided fields
119
+ validated_data = {}
120
+ for field_name, value in data.items():
121
+ if field_name in type_hints:
122
+ expected_type = type_hints[field_name]
123
+
124
+ # Handle simple type checking
125
+ if not check_type_compatibility(value, expected_type):
126
+ raise ValueError(
127
+ f"Field '{field_name}' expected type {expected_type}, got {type(value)} with value {value}"
128
+ )
129
+
130
+ validated_data[field_name] = value
131
+
132
+ return validated_data
agno/utils/events.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Any, List, Optional
1
+ from typing import Any, Dict, List, Optional, Union
2
2
 
3
3
  from agno.media import Audio, Image
4
4
  from agno.models.message import Citations
@@ -11,17 +11,27 @@ from agno.run.agent import (
11
11
  OutputModelResponseStartedEvent,
12
12
  ParserModelResponseCompletedEvent,
13
13
  ParserModelResponseStartedEvent,
14
+ PostHookCompletedEvent,
15
+ PostHookStartedEvent,
16
+ PreHookCompletedEvent,
17
+ PreHookStartedEvent,
14
18
  ReasoningCompletedEvent,
15
19
  ReasoningStartedEvent,
16
20
  ReasoningStepEvent,
17
21
  RunCancelledEvent,
18
22
  RunCompletedEvent,
23
+ RunContentCompletedEvent,
19
24
  RunContentEvent,
20
25
  RunContinuedEvent,
21
26
  RunErrorEvent,
27
+ RunEvent,
28
+ RunInput,
22
29
  RunOutput,
30
+ RunOutputEvent,
23
31
  RunPausedEvent,
24
32
  RunStartedEvent,
33
+ SessionSummaryCompletedEvent,
34
+ SessionSummaryStartedEvent,
25
35
  ToolCallCompletedEvent,
26
36
  ToolCallStartedEvent,
27
37
  )
@@ -31,17 +41,25 @@ from agno.run.team import OutputModelResponseCompletedEvent as TeamOutputModelRe
31
41
  from agno.run.team import OutputModelResponseStartedEvent as TeamOutputModelResponseStartedEvent
32
42
  from agno.run.team import ParserModelResponseCompletedEvent as TeamParserModelResponseCompletedEvent
33
43
  from agno.run.team import ParserModelResponseStartedEvent as TeamParserModelResponseStartedEvent
44
+ from agno.run.team import PostHookCompletedEvent as TeamPostHookCompletedEvent
45
+ from agno.run.team import PostHookStartedEvent as TeamPostHookStartedEvent
46
+ from agno.run.team import PreHookCompletedEvent as TeamPreHookCompletedEvent
47
+ from agno.run.team import PreHookStartedEvent as TeamPreHookStartedEvent
34
48
  from agno.run.team import ReasoningCompletedEvent as TeamReasoningCompletedEvent
35
49
  from agno.run.team import ReasoningStartedEvent as TeamReasoningStartedEvent
36
50
  from agno.run.team import ReasoningStepEvent as TeamReasoningStepEvent
37
51
  from agno.run.team import RunCancelledEvent as TeamRunCancelledEvent
38
52
  from agno.run.team import RunCompletedEvent as TeamRunCompletedEvent
53
+ from agno.run.team import RunContentCompletedEvent as TeamRunContentCompletedEvent
39
54
  from agno.run.team import RunContentEvent as TeamRunContentEvent
40
55
  from agno.run.team import RunErrorEvent as TeamRunErrorEvent
41
56
  from agno.run.team import RunStartedEvent as TeamRunStartedEvent
42
- from agno.run.team import TeamRunOutput
57
+ from agno.run.team import SessionSummaryCompletedEvent as TeamSessionSummaryCompletedEvent
58
+ from agno.run.team import SessionSummaryStartedEvent as TeamSessionSummaryStartedEvent
59
+ from agno.run.team import TeamRunEvent, TeamRunInput, TeamRunOutput, TeamRunOutputEvent
43
60
  from agno.run.team import ToolCallCompletedEvent as TeamToolCallCompletedEvent
44
61
  from agno.run.team import ToolCallStartedEvent as TeamToolCallStartedEvent
62
+ from agno.session.summary import SessionSummary
45
63
 
46
64
 
47
65
  def create_team_run_started_event(from_run_response: TeamRunOutput) -> TeamRunStartedEvent:
@@ -76,6 +94,7 @@ def create_team_run_completed_event(from_run_response: TeamRunOutput) -> TeamRun
76
94
  content_type=from_run_response.content_type, # type: ignore
77
95
  reasoning_content=from_run_response.reasoning_content, # type: ignore
78
96
  citations=from_run_response.citations, # type: ignore
97
+ model_provider_data=from_run_response.model_provider_data, # type: ignore
79
98
  images=from_run_response.images, # type: ignore
80
99
  videos=from_run_response.videos, # type: ignore
81
100
  audio=from_run_response.audio, # type: ignore
@@ -87,6 +106,7 @@ def create_team_run_completed_event(from_run_response: TeamRunOutput) -> TeamRun
87
106
  member_responses=from_run_response.member_responses, # type: ignore
88
107
  metadata=from_run_response.metadata, # type: ignore
89
108
  metrics=from_run_response.metrics, # type: ignore
109
+ session_state=from_run_response.session_state, # type: ignore
90
110
  )
91
111
 
92
112
 
@@ -100,6 +120,7 @@ def create_run_completed_event(from_run_response: RunOutput) -> RunCompletedEven
100
120
  content_type=from_run_response.content_type, # type: ignore
101
121
  reasoning_content=from_run_response.reasoning_content, # type: ignore
102
122
  citations=from_run_response.citations, # type: ignore
123
+ model_provider_data=from_run_response.model_provider_data, # type: ignore
103
124
  images=from_run_response.images, # type: ignore
104
125
  videos=from_run_response.videos, # type: ignore
105
126
  audio=from_run_response.audio, # type: ignore
@@ -110,6 +131,7 @@ def create_run_completed_event(from_run_response: RunOutput) -> RunCompletedEven
110
131
  reasoning_messages=from_run_response.reasoning_messages, # type: ignore
111
132
  metadata=from_run_response.metadata, # type: ignore
112
133
  metrics=from_run_response.metrics, # type: ignore
134
+ session_state=from_run_response.session_state, # type: ignore
113
135
  )
114
136
 
115
137
 
@@ -175,6 +197,114 @@ def create_run_cancelled_event(from_run_response: RunOutput, reason: str) -> Run
175
197
  )
176
198
 
177
199
 
200
+ def create_pre_hook_started_event(
201
+ from_run_response: RunOutput, pre_hook_name: Optional[str] = None, run_input: Optional[RunInput] = None
202
+ ) -> PreHookStartedEvent:
203
+ from copy import deepcopy
204
+
205
+ return PreHookStartedEvent(
206
+ session_id=from_run_response.session_id,
207
+ agent_id=from_run_response.agent_id, # type: ignore
208
+ agent_name=from_run_response.agent_name, # type: ignore
209
+ run_id=from_run_response.run_id,
210
+ pre_hook_name=pre_hook_name,
211
+ run_input=deepcopy(run_input),
212
+ )
213
+
214
+
215
+ def create_team_pre_hook_started_event(
216
+ from_run_response: TeamRunOutput, pre_hook_name: Optional[str] = None, run_input: Optional[TeamRunInput] = None
217
+ ) -> TeamPreHookStartedEvent:
218
+ from copy import deepcopy
219
+
220
+ return TeamPreHookStartedEvent(
221
+ session_id=from_run_response.session_id,
222
+ team_id=from_run_response.team_id, # type: ignore
223
+ team_name=from_run_response.team_name, # type: ignore
224
+ run_id=from_run_response.run_id,
225
+ pre_hook_name=pre_hook_name,
226
+ run_input=deepcopy(run_input),
227
+ )
228
+
229
+
230
+ def create_pre_hook_completed_event(
231
+ from_run_response: RunOutput, pre_hook_name: Optional[str] = None, run_input: Optional[RunInput] = None
232
+ ) -> PreHookCompletedEvent:
233
+ from copy import deepcopy
234
+
235
+ return PreHookCompletedEvent(
236
+ session_id=from_run_response.session_id,
237
+ agent_id=from_run_response.agent_id, # type: ignore
238
+ agent_name=from_run_response.agent_name, # type: ignore
239
+ run_id=from_run_response.run_id,
240
+ pre_hook_name=pre_hook_name,
241
+ run_input=deepcopy(run_input),
242
+ )
243
+
244
+
245
+ def create_team_pre_hook_completed_event(
246
+ from_run_response: TeamRunOutput, pre_hook_name: Optional[str] = None, run_input: Optional[TeamRunInput] = None
247
+ ) -> TeamPreHookCompletedEvent:
248
+ from copy import deepcopy
249
+
250
+ return TeamPreHookCompletedEvent(
251
+ session_id=from_run_response.session_id,
252
+ team_id=from_run_response.team_id, # type: ignore
253
+ team_name=from_run_response.team_name, # type: ignore
254
+ run_id=from_run_response.run_id,
255
+ pre_hook_name=pre_hook_name,
256
+ run_input=deepcopy(run_input),
257
+ )
258
+
259
+
260
+ def create_post_hook_started_event(
261
+ from_run_response: RunOutput, post_hook_name: Optional[str] = None
262
+ ) -> PostHookStartedEvent:
263
+ return PostHookStartedEvent(
264
+ session_id=from_run_response.session_id,
265
+ agent_id=from_run_response.agent_id, # type: ignore
266
+ agent_name=from_run_response.agent_name, # type: ignore
267
+ run_id=from_run_response.run_id,
268
+ post_hook_name=post_hook_name,
269
+ )
270
+
271
+
272
+ def create_team_post_hook_started_event(
273
+ from_run_response: TeamRunOutput, post_hook_name: Optional[str] = None
274
+ ) -> TeamPostHookStartedEvent:
275
+ return TeamPostHookStartedEvent(
276
+ session_id=from_run_response.session_id,
277
+ team_id=from_run_response.team_id, # type: ignore
278
+ team_name=from_run_response.team_name, # type: ignore
279
+ run_id=from_run_response.run_id,
280
+ post_hook_name=post_hook_name,
281
+ )
282
+
283
+
284
+ def create_post_hook_completed_event(
285
+ from_run_response: RunOutput, post_hook_name: Optional[str] = None
286
+ ) -> PostHookCompletedEvent:
287
+ return PostHookCompletedEvent(
288
+ session_id=from_run_response.session_id,
289
+ agent_id=from_run_response.agent_id, # type: ignore
290
+ agent_name=from_run_response.agent_name, # type: ignore
291
+ run_id=from_run_response.run_id,
292
+ post_hook_name=post_hook_name,
293
+ )
294
+
295
+
296
+ def create_team_post_hook_completed_event(
297
+ from_run_response: TeamRunOutput, post_hook_name: Optional[str] = None
298
+ ) -> TeamPostHookCompletedEvent:
299
+ return TeamPostHookCompletedEvent(
300
+ session_id=from_run_response.session_id,
301
+ team_id=from_run_response.team_id, # type: ignore
302
+ team_name=from_run_response.team_name, # type: ignore
303
+ run_id=from_run_response.run_id,
304
+ post_hook_name=post_hook_name,
305
+ )
306
+
307
+
178
308
  def create_memory_update_started_event(from_run_response: RunOutput) -> MemoryUpdateStartedEvent:
179
309
  return MemoryUpdateStartedEvent(
180
310
  session_id=from_run_response.session_id,
@@ -211,6 +341,50 @@ def create_team_memory_update_completed_event(from_run_response: TeamRunOutput)
211
341
  )
212
342
 
213
343
 
344
+ def create_team_session_summary_started_event(
345
+ from_run_response: TeamRunOutput,
346
+ ) -> TeamSessionSummaryStartedEvent:
347
+ return TeamSessionSummaryStartedEvent(
348
+ session_id=from_run_response.session_id,
349
+ team_id=from_run_response.team_id, # type: ignore
350
+ team_name=from_run_response.team_name, # type: ignore
351
+ run_id=from_run_response.run_id,
352
+ )
353
+
354
+
355
+ def create_team_session_summary_completed_event(
356
+ from_run_response: TeamRunOutput, session_summary: Optional[SessionSummary] = None
357
+ ) -> TeamSessionSummaryCompletedEvent:
358
+ return TeamSessionSummaryCompletedEvent(
359
+ session_id=from_run_response.session_id,
360
+ team_id=from_run_response.team_id, # type: ignore
361
+ team_name=from_run_response.team_name, # type: ignore
362
+ run_id=from_run_response.run_id,
363
+ session_summary=session_summary,
364
+ )
365
+
366
+
367
+ def create_session_summary_started_event(from_run_response: RunOutput) -> SessionSummaryStartedEvent:
368
+ return SessionSummaryStartedEvent(
369
+ session_id=from_run_response.session_id,
370
+ agent_id=from_run_response.agent_id, # type: ignore
371
+ agent_name=from_run_response.agent_name, # type: ignore
372
+ run_id=from_run_response.run_id,
373
+ )
374
+
375
+
376
+ def create_session_summary_completed_event(
377
+ from_run_response: RunOutput, session_summary: Optional[SessionSummary] = None
378
+ ) -> SessionSummaryCompletedEvent:
379
+ return SessionSummaryCompletedEvent(
380
+ session_id=from_run_response.session_id,
381
+ agent_id=from_run_response.agent_id, # type: ignore
382
+ agent_name=from_run_response.agent_name, # type: ignore
383
+ run_id=from_run_response.run_id,
384
+ session_summary=session_summary,
385
+ )
386
+
387
+
214
388
  def create_reasoning_started_event(from_run_response: RunOutput) -> ReasoningStartedEvent:
215
389
  return ReasoningStartedEvent(
216
390
  session_id=from_run_response.session_id,
@@ -343,6 +517,7 @@ def create_run_output_content_event(
343
517
  content_type: Optional[str] = None,
344
518
  reasoning_content: Optional[str] = None,
345
519
  redacted_reasoning_content: Optional[str] = None,
520
+ model_provider_data: Optional[Dict[str, Any]] = None,
346
521
  citations: Optional[Citations] = None,
347
522
  response_audio: Optional[Audio] = None,
348
523
  image: Optional[Image] = None,
@@ -364,6 +539,7 @@ def create_run_output_content_event(
364
539
  additional_input=from_run_response.additional_input,
365
540
  reasoning_steps=from_run_response.reasoning_steps,
366
541
  reasoning_messages=from_run_response.reasoning_messages,
542
+ model_provider_data=model_provider_data,
367
543
  )
368
544
 
369
545
 
@@ -374,6 +550,7 @@ def create_team_run_output_content_event(
374
550
  reasoning_content: Optional[str] = None,
375
551
  redacted_reasoning_content: Optional[str] = None,
376
552
  citations: Optional[Citations] = None,
553
+ model_provider_data: Optional[Dict[str, Any]] = None,
377
554
  response_audio: Optional[Audio] = None,
378
555
  image: Optional[Image] = None,
379
556
  ) -> TeamRunContentEvent:
@@ -388,6 +565,7 @@ def create_team_run_output_content_event(
388
565
  content_type=content_type or "str",
389
566
  reasoning_content=thinking_combined,
390
567
  citations=citations,
568
+ model_provider_data=model_provider_data,
391
569
  response_audio=response_audio,
392
570
  image=image,
393
571
  references=from_run_response.references, # type: ignore
@@ -397,6 +575,28 @@ def create_team_run_output_content_event(
397
575
  )
398
576
 
399
577
 
578
+ def create_run_content_completed_event(
579
+ from_run_response: RunOutput,
580
+ ) -> RunContentCompletedEvent:
581
+ return RunContentCompletedEvent(
582
+ session_id=from_run_response.session_id,
583
+ agent_id=from_run_response.agent_id, # type: ignore
584
+ agent_name=from_run_response.agent_name, # type: ignore
585
+ run_id=from_run_response.run_id,
586
+ )
587
+
588
+
589
+ def create_team_run_content_completed_event(
590
+ from_run_response: TeamRunOutput,
591
+ ) -> TeamRunContentCompletedEvent:
592
+ return TeamRunContentCompletedEvent(
593
+ session_id=from_run_response.session_id,
594
+ team_id=from_run_response.team_id, # type: ignore
595
+ team_name=from_run_response.team_name, # type: ignore
596
+ run_id=from_run_response.run_id,
597
+ )
598
+
599
+
400
600
  def create_parser_model_response_started_event(
401
601
  from_run_response: RunOutput,
402
602
  ) -> ParserModelResponseStartedEvent:
@@ -479,3 +679,18 @@ def create_team_output_model_response_completed_event(
479
679
  team_name=from_run_response.team_name, # type: ignore
480
680
  run_id=from_run_response.run_id,
481
681
  )
682
+
683
+
684
+ def handle_event(
685
+ event: Union[RunOutputEvent, TeamRunOutputEvent],
686
+ run_response: Union[RunOutput, TeamRunOutput],
687
+ events_to_skip: Optional[List[Union[RunEvent, TeamRunEvent]]] = None,
688
+ store_events: bool = False,
689
+ ) -> Union[RunOutputEvent, TeamRunOutputEvent]:
690
+ # We only store events that are not run_response_content events
691
+ events_to_skip = [event.value for event in events_to_skip] if events_to_skip else []
692
+ if store_events and event.event not in events_to_skip:
693
+ if run_response.events is None:
694
+ run_response.events = []
695
+ run_response.events.append(event) # type: ignore
696
+ return event