agno 2.0.0rc2__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 (331) hide show
  1. agno/agent/agent.py +6009 -2874
  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 +595 -187
  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 +3 -0
  105. agno/knowledge/types.py +9 -0
  106. agno/knowledge/utils.py +20 -0
  107. agno/media.py +339 -266
  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 +1011 -566
  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 +110 -37
  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 +143 -4
  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 +60 -6
  142. agno/models/openai/chat.py +102 -43
  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 +81 -5
  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 -175
  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 +266 -112
  205. agno/run/base.py +53 -24
  206. agno/run/team.py +252 -111
  207. agno/run/workflow.py +156 -45
  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 -1692
  213. agno/tools/brightdata.py +3 -3
  214. agno/tools/cartesia.py +3 -5
  215. agno/tools/dalle.py +9 -8
  216. agno/tools/decorator.py +4 -2
  217. agno/tools/desi_vocal.py +2 -2
  218. agno/tools/duckduckgo.py +15 -11
  219. agno/tools/e2b.py +20 -13
  220. agno/tools/eleven_labs.py +26 -28
  221. agno/tools/exa.py +21 -16
  222. agno/tools/fal.py +4 -4
  223. agno/tools/file.py +153 -23
  224. agno/tools/file_generation.py +350 -0
  225. agno/tools/firecrawl.py +4 -4
  226. agno/tools/function.py +257 -37
  227. agno/tools/giphy.py +2 -2
  228. agno/tools/gmail.py +238 -14
  229. agno/tools/google_drive.py +270 -0
  230. agno/tools/googlecalendar.py +36 -8
  231. agno/tools/googlesheets.py +20 -5
  232. agno/tools/jira.py +20 -0
  233. agno/tools/knowledge.py +3 -3
  234. agno/tools/lumalab.py +3 -3
  235. agno/tools/mcp/__init__.py +10 -0
  236. agno/tools/mcp/mcp.py +331 -0
  237. agno/tools/mcp/multi_mcp.py +347 -0
  238. agno/tools/mcp/params.py +24 -0
  239. agno/tools/mcp_toolbox.py +284 -0
  240. agno/tools/mem0.py +11 -17
  241. agno/tools/memori.py +1 -53
  242. agno/tools/memory.py +419 -0
  243. agno/tools/models/azure_openai.py +2 -2
  244. agno/tools/models/gemini.py +3 -3
  245. agno/tools/models/groq.py +3 -5
  246. agno/tools/models/nebius.py +7 -7
  247. agno/tools/models_labs.py +25 -15
  248. agno/tools/notion.py +204 -0
  249. agno/tools/openai.py +4 -9
  250. agno/tools/opencv.py +3 -3
  251. agno/tools/parallel.py +314 -0
  252. agno/tools/replicate.py +7 -7
  253. agno/tools/scrapegraph.py +58 -31
  254. agno/tools/searxng.py +2 -2
  255. agno/tools/serper.py +2 -2
  256. agno/tools/slack.py +18 -3
  257. agno/tools/spider.py +2 -2
  258. agno/tools/tavily.py +146 -0
  259. agno/tools/whatsapp.py +1 -1
  260. agno/tools/workflow.py +278 -0
  261. agno/tools/yfinance.py +12 -11
  262. agno/utils/agent.py +820 -0
  263. agno/utils/audio.py +27 -0
  264. agno/utils/common.py +90 -1
  265. agno/utils/events.py +222 -7
  266. agno/utils/gemini.py +181 -23
  267. agno/utils/hooks.py +57 -0
  268. agno/utils/http.py +111 -0
  269. agno/utils/knowledge.py +12 -5
  270. agno/utils/log.py +1 -0
  271. agno/utils/mcp.py +95 -5
  272. agno/utils/media.py +188 -10
  273. agno/utils/merge_dict.py +22 -1
  274. agno/utils/message.py +60 -0
  275. agno/utils/models/claude.py +40 -11
  276. agno/utils/models/cohere.py +1 -1
  277. agno/utils/models/watsonx.py +1 -1
  278. agno/utils/openai.py +1 -1
  279. agno/utils/print_response/agent.py +105 -21
  280. agno/utils/print_response/team.py +103 -38
  281. agno/utils/print_response/workflow.py +251 -34
  282. agno/utils/reasoning.py +22 -1
  283. agno/utils/serialize.py +32 -0
  284. agno/utils/streamlit.py +16 -10
  285. agno/utils/string.py +41 -0
  286. agno/utils/team.py +98 -9
  287. agno/utils/tools.py +1 -1
  288. agno/vectordb/base.py +23 -4
  289. agno/vectordb/cassandra/cassandra.py +65 -9
  290. agno/vectordb/chroma/chromadb.py +182 -38
  291. agno/vectordb/clickhouse/clickhousedb.py +64 -11
  292. agno/vectordb/couchbase/couchbase.py +105 -10
  293. agno/vectordb/lancedb/lance_db.py +183 -135
  294. agno/vectordb/langchaindb/langchaindb.py +25 -7
  295. agno/vectordb/lightrag/lightrag.py +17 -3
  296. agno/vectordb/llamaindex/__init__.py +3 -0
  297. agno/vectordb/llamaindex/llamaindexdb.py +46 -7
  298. agno/vectordb/milvus/milvus.py +126 -9
  299. agno/vectordb/mongodb/__init__.py +7 -1
  300. agno/vectordb/mongodb/mongodb.py +112 -7
  301. agno/vectordb/pgvector/pgvector.py +142 -21
  302. agno/vectordb/pineconedb/pineconedb.py +80 -8
  303. agno/vectordb/qdrant/qdrant.py +125 -39
  304. agno/vectordb/redis/__init__.py +9 -0
  305. agno/vectordb/redis/redisdb.py +694 -0
  306. agno/vectordb/singlestore/singlestore.py +111 -25
  307. agno/vectordb/surrealdb/surrealdb.py +31 -5
  308. agno/vectordb/upstashdb/upstashdb.py +76 -8
  309. agno/vectordb/weaviate/weaviate.py +86 -15
  310. agno/workflow/__init__.py +2 -0
  311. agno/workflow/agent.py +299 -0
  312. agno/workflow/condition.py +112 -18
  313. agno/workflow/loop.py +69 -10
  314. agno/workflow/parallel.py +266 -118
  315. agno/workflow/router.py +110 -17
  316. agno/workflow/step.py +645 -136
  317. agno/workflow/steps.py +65 -6
  318. agno/workflow/types.py +71 -33
  319. agno/workflow/workflow.py +2113 -300
  320. agno-2.3.0.dist-info/METADATA +618 -0
  321. agno-2.3.0.dist-info/RECORD +577 -0
  322. agno-2.3.0.dist-info/licenses/LICENSE +201 -0
  323. agno/knowledge/reader/url_reader.py +0 -128
  324. agno/tools/googlesearch.py +0 -98
  325. agno/tools/mcp.py +0 -610
  326. agno/utils/models/aws_claude.py +0 -170
  327. agno-2.0.0rc2.dist-info/METADATA +0 -355
  328. agno-2.0.0rc2.dist-info/RECORD +0 -515
  329. agno-2.0.0rc2.dist-info/licenses/LICENSE +0 -375
  330. {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
  331. {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from typing import Optional
4
4
  from uuid import uuid4
5
5
 
6
6
  from agno.agent import Agent
7
- from agno.media import ImageArtifact
7
+ from agno.media import Image
8
8
  from agno.models.nebius import Nebius
9
9
  from agno.tools import Toolkit
10
10
  from agno.tools.function import ToolResult
@@ -12,12 +12,12 @@ from agno.utils.log import log_error, log_warning
12
12
 
13
13
 
14
14
  class NebiusTools(Toolkit):
15
- """Tools for interacting with Nebius AI Studio's text-to-image API"""
15
+ """Tools for interacting with Nebius Token Factory's text-to-image API"""
16
16
 
17
17
  def __init__(
18
18
  self,
19
19
  api_key: Optional[str] = None,
20
- base_url: str = "https://api.studio.nebius.com/v1",
20
+ base_url: str = "https://api.tokenfactory.nebius.com/v1",
21
21
  image_model: str = "black-forest-labs/flux-schnell",
22
22
  image_quality: Optional[str] = "standard",
23
23
  image_size: Optional[str] = "1024x1024",
@@ -26,11 +26,11 @@ class NebiusTools(Toolkit):
26
26
  all: bool = False,
27
27
  **kwargs,
28
28
  ):
29
- """Initialize Nebius AI Studio text-to-image tools.
29
+ """Initialize Nebius Token Factory text-to-image tools.
30
30
 
31
31
  Args:
32
32
  api_key: Nebius API key. If not provided, will look for NEBIUS_API_KEY environment variable.
33
- base_url: The base URL for the Nebius AI Studio API. This should be configured according to Nebius's documentation.
33
+ base_url: The base URL for the Nebius Token Factory API. This should be configured according to Nebius's documentation.
34
34
  image_model: The model to use for generation. Options include:
35
35
  - "black-forest-labs/flux-schnell" (fastest)
36
36
  - "black-forest-labs/flux-dev" (balanced)
@@ -69,7 +69,7 @@ class NebiusTools(Toolkit):
69
69
  agent: Agent,
70
70
  prompt: str,
71
71
  ) -> ToolResult:
72
- """Generate images based on a text prompt using Nebius AI Studio.
72
+ """Generate images based on a text prompt using Nebius Token Factory.
73
73
 
74
74
  Args:
75
75
  agent: The agent instance for adding images
@@ -108,7 +108,7 @@ class NebiusTools(Toolkit):
108
108
  media_id = str(uuid4())
109
109
 
110
110
  # Create ImageArtifact with raw bytes
111
- image_artifact = ImageArtifact(
111
+ image_artifact = Image(
112
112
  id=media_id, content=image_content_bytes, mime_type="image/png", original_prompt=prompt
113
113
  )
114
114
 
agno/tools/models_labs.py CHANGED
@@ -4,10 +4,8 @@ from os import getenv
4
4
  from typing import Any, Dict, List, Optional, Union
5
5
  from uuid import uuid4
6
6
 
7
- from agno.agent import Agent
8
- from agno.media import AudioArtifact, ImageArtifact, VideoArtifact
7
+ from agno.media import Audio, Image, Video
9
8
  from agno.models.response import FileType
10
- from agno.team import Team
11
9
  from agno.tools import Toolkit
12
10
  from agno.tools.function import ToolResult
13
11
  from agno.utils.log import log_debug, log_info, logger
@@ -22,12 +20,14 @@ MODELS_LAB_URLS = {
22
20
  "MP4": "https://modelslab.com/api/v6/video/text2video",
23
21
  "MP3": "https://modelslab.com/api/v6/voice/music_gen",
24
22
  "GIF": "https://modelslab.com/api/v6/video/text2video",
23
+ "WAV": "https://modelslab.com/api/v6/voice/sfx",
25
24
  }
26
25
 
27
26
  MODELS_LAB_FETCH_URLS = {
28
27
  "MP4": "https://modelslab.com/api/v6/video/fetch",
29
28
  "MP3": "https://modelslab.com/api/v6/voice/fetch",
30
29
  "GIF": "https://modelslab.com/api/v6/video/fetch",
30
+ "WAV": "https://modelslab.com/api/v6/voice/fetch",
31
31
  }
32
32
 
33
33
 
@@ -78,6 +78,13 @@ class ModelsLabTools(Toolkit):
78
78
  "output_type": self.file_type.value,
79
79
  }
80
80
  base_payload |= video_template # Use |= instead of update()
81
+ elif self.file_type == FileType.WAV:
82
+ sfx_template = {
83
+ "duration": 10,
84
+ "output_format": "wav",
85
+ "temp": False,
86
+ }
87
+ base_payload |= sfx_template # Use |= instead of update()
81
88
  else:
82
89
  audio_template = {
83
90
  "base64": False,
@@ -89,20 +96,20 @@ class ModelsLabTools(Toolkit):
89
96
 
90
97
  def _create_media_artifacts(self, media_id: str, media_url: str, eta: Optional[str] = None) -> Dict[str, List]:
91
98
  """Create appropriate media artifacts based on file type."""
92
- artifacts: Dict[str, List[Union[ImageArtifact, VideoArtifact, AudioArtifact]]] = {
99
+ artifacts: Dict[str, List[Union[Image, Video, Audio]]] = {
93
100
  "images": [],
94
101
  "videos": [],
95
102
  "audios": [],
96
103
  }
97
104
 
98
105
  if self.file_type == FileType.MP4:
99
- video_artifact = VideoArtifact(id=str(media_id), url=media_url, eta=str(eta))
106
+ video_artifact = Video(id=str(media_id), url=media_url, eta=str(eta))
100
107
  artifacts["videos"].append(video_artifact)
101
108
  elif self.file_type == FileType.GIF:
102
- image_artifact = ImageArtifact(id=str(media_id), url=media_url)
109
+ image_artifact = Image(id=str(media_id), url=media_url)
103
110
  artifacts["images"].append(image_artifact)
104
- elif self.file_type == FileType.MP3:
105
- audio_artifact = AudioArtifact(id=str(media_id), url=media_url)
111
+ elif self.file_type in [FileType.MP3, FileType.WAV]:
112
+ audio_artifact = Audio(id=str(media_id), url=media_url)
106
113
  artifacts["audios"].append(audio_artifact)
107
114
 
108
115
  return artifacts
@@ -131,7 +138,7 @@ class ModelsLabTools(Toolkit):
131
138
 
132
139
  return False
133
140
 
134
- def generate_media(self, agent: Union[Agent, Team], prompt: str) -> ToolResult:
141
+ def generate_media(self, prompt: str) -> ToolResult:
135
142
  """Generate media (video, image, or audio) given a prompt."""
136
143
  if not self.api_key:
137
144
  return ToolResult(content="Please set the MODELS_LAB_API_KEY")
@@ -157,7 +164,6 @@ class ModelsLabTools(Toolkit):
157
164
  return ToolResult(content=f"Error: {result['error']}")
158
165
 
159
166
  eta = result.get("eta")
160
- url_links = result.get("future_links")
161
167
  media_id = str(uuid4())
162
168
 
163
169
  # Collect all media artifacts
@@ -165,17 +171,21 @@ class ModelsLabTools(Toolkit):
165
171
  all_videos = []
166
172
  all_audios = []
167
173
 
174
+ if self.file_type == FileType.WAV:
175
+ url_links = result.get("output", [])
176
+ else:
177
+ url_links = result.get("future_links")
168
178
  for media_url in url_links:
169
179
  artifacts = self._create_media_artifacts(media_id, media_url, str(eta))
170
180
  all_images.extend(artifacts["images"])
171
181
  all_videos.extend(artifacts["videos"])
172
182
  all_audios.extend(artifacts["audios"])
173
183
 
174
- if self.wait_for_completion and isinstance(eta, int):
175
- if self._wait_for_media(media_id, eta):
176
- log_info("Media generation completed successfully")
177
- else:
178
- logger.warning("Media generation timed out")
184
+ if self.wait_for_completion and isinstance(eta, int):
185
+ if self._wait_for_media(media_id, eta):
186
+ log_info("Media generation completed successfully")
187
+ else:
188
+ logger.warning("Media generation timed out")
179
189
 
180
190
  # Return ToolResult with appropriate media artifacts
181
191
  return ToolResult(
agno/tools/notion.py ADDED
@@ -0,0 +1,204 @@
1
+ import json
2
+ import os
3
+ from typing import Any, Dict, List, Optional, cast
4
+
5
+ from agno.tools import Toolkit
6
+ from agno.utils.log import log_debug, logger
7
+
8
+ try:
9
+ from notion_client import Client
10
+ except ImportError:
11
+ raise ImportError("`notion-client` not installed. Please install using `pip install notion-client`")
12
+
13
+
14
+ class NotionTools(Toolkit):
15
+ """
16
+ Notion toolkit for creating and managing Notion pages.
17
+
18
+ Args:
19
+ api_key (Optional[str]): Notion API key (integration token). If not provided, uses NOTION_API_KEY env var.
20
+ database_id (Optional[str]): The ID of the database to work with. If not provided, uses NOTION_DATABASE_ID env var.
21
+ enable_create_page (bool): Enable creating pages. Default is True.
22
+ enable_update_page (bool): Enable updating pages. Default is True.
23
+ enable_search_pages (bool): Enable searching pages. Default is True.
24
+ all (bool): Enable all tools. Overrides individual flags when True. Default is False.
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ api_key: Optional[str] = None,
30
+ database_id: Optional[str] = None,
31
+ enable_create_page: bool = True,
32
+ enable_update_page: bool = True,
33
+ enable_search_pages: bool = True,
34
+ all: bool = False,
35
+ **kwargs,
36
+ ):
37
+ self.api_key = api_key or os.getenv("NOTION_API_KEY")
38
+ self.database_id = database_id or os.getenv("NOTION_DATABASE_ID")
39
+
40
+ if not self.api_key:
41
+ raise ValueError(
42
+ "Notion API key is required. Either pass api_key parameter or set NOTION_API_KEY environment variable."
43
+ )
44
+ if not self.database_id:
45
+ raise ValueError(
46
+ "Notion database ID is required. Either pass database_id parameter or set NOTION_DATABASE_ID environment variable."
47
+ )
48
+
49
+ self.client = Client(auth=self.api_key)
50
+
51
+ tools: List[Any] = []
52
+ if all or enable_create_page:
53
+ tools.append(self.create_page)
54
+ if all or enable_update_page:
55
+ tools.append(self.update_page)
56
+ if all or enable_search_pages:
57
+ tools.append(self.search_pages)
58
+
59
+ super().__init__(name="notion_tools", tools=tools, **kwargs)
60
+
61
+ def create_page(self, title: str, tag: str, content: str) -> str:
62
+ """Create a new page in the Notion database with a title, tag, and content.
63
+
64
+ Args:
65
+ title (str): The title of the page
66
+ tag (str): The tag/category for the page (e.g., travel, tech, general-blogs, fashion, documents)
67
+ content (str): The content to add to the page
68
+
69
+ Returns:
70
+ str: JSON string with page creation details
71
+ """
72
+ try:
73
+ log_debug(f"Creating Notion page with title: {title}, tag: {tag}")
74
+
75
+ # Create the page in the database
76
+ new_page = cast(
77
+ Dict[str, Any],
78
+ self.client.pages.create(
79
+ parent={"database_id": self.database_id},
80
+ properties={"Name": {"title": [{"text": {"content": title}}]}, "Tag": {"select": {"name": tag}}},
81
+ children=[
82
+ {
83
+ "object": "block",
84
+ "type": "paragraph",
85
+ "paragraph": {"rich_text": [{"type": "text", "text": {"content": content}}]},
86
+ }
87
+ ],
88
+ ),
89
+ )
90
+
91
+ result = {"success": True, "page_id": new_page["id"], "url": new_page["url"], "title": title, "tag": tag}
92
+ return json.dumps(result, indent=2)
93
+
94
+ except Exception as e:
95
+ logger.exception(e)
96
+ return json.dumps({"success": False, "error": str(e)})
97
+
98
+ def update_page(self, page_id: str, content: str) -> str:
99
+ """Add content to an existing Notion page.
100
+
101
+ Args:
102
+ page_id (str): The ID of the page to update
103
+ content (str): The content to append to the page
104
+
105
+ Returns:
106
+ str: JSON string with update status
107
+ """
108
+ try:
109
+ log_debug(f"Updating Notion page: {page_id}")
110
+
111
+ # Append content to the page
112
+ self.client.blocks.children.append(
113
+ block_id=page_id,
114
+ children=[
115
+ {
116
+ "object": "block",
117
+ "type": "paragraph",
118
+ "paragraph": {"rich_text": [{"type": "text", "text": {"content": content}}]},
119
+ }
120
+ ],
121
+ )
122
+
123
+ result = {"success": True, "page_id": page_id, "message": "Content added successfully"}
124
+ return json.dumps(result, indent=2)
125
+
126
+ except Exception as e:
127
+ logger.exception(e)
128
+ return json.dumps({"success": False, "error": str(e)})
129
+
130
+ def search_pages(self, tag: str) -> str:
131
+ """Search for pages in the database by tag.
132
+
133
+ Args:
134
+ tag (str): The tag to search for
135
+
136
+ Returns:
137
+ str: JSON string with list of matching pages
138
+ """
139
+ try:
140
+ log_debug(f"Searching for pages with tag: {tag}")
141
+
142
+ import httpx
143
+
144
+ headers = {
145
+ "Authorization": f"Bearer {self.api_key}",
146
+ "Notion-Version": "2022-06-28",
147
+ "Content-Type": "application/json",
148
+ }
149
+
150
+ payload = {"filter": {"property": "Tag", "select": {"equals": tag}}}
151
+
152
+ # The SDK client does not support the query method
153
+ response = httpx.post(
154
+ f"https://api.notion.com/v1/databases/{self.database_id}/query",
155
+ headers=headers,
156
+ json=payload,
157
+ timeout=30.0,
158
+ )
159
+
160
+ if response.status_code != 200:
161
+ return json.dumps(
162
+ {
163
+ "success": False,
164
+ "error": f"API request failed with status {response.status_code}",
165
+ "message": response.text,
166
+ }
167
+ )
168
+
169
+ data = response.json()
170
+ pages = []
171
+
172
+ for page in data.get("results", []):
173
+ try:
174
+ page_title = "Untitled"
175
+ if page.get("properties", {}).get("Name", {}).get("title"):
176
+ page_title = page["properties"]["Name"]["title"][0]["text"]["content"]
177
+
178
+ page_tag = None
179
+ if page.get("properties", {}).get("Tag", {}).get("select"):
180
+ page_tag = page["properties"]["Tag"]["select"]["name"]
181
+
182
+ page_info = {
183
+ "page_id": page["id"],
184
+ "title": page_title,
185
+ "tag": page_tag,
186
+ "url": page.get("url", ""),
187
+ }
188
+ pages.append(page_info)
189
+ except Exception as page_error:
190
+ log_debug(f"Error parsing page: {page_error}")
191
+ continue
192
+
193
+ result = {"success": True, "count": len(pages), "pages": pages}
194
+ return json.dumps(result, indent=2)
195
+
196
+ except Exception as e:
197
+ logger.exception(e)
198
+ return json.dumps(
199
+ {
200
+ "success": False,
201
+ "error": str(e),
202
+ "message": "Failed to search pages. Make sure the database is shared with the integration and has a 'Tag' property.",
203
+ }
204
+ )
agno/tools/openai.py CHANGED
@@ -3,7 +3,7 @@ from typing import Any, List, Literal, Optional, Union
3
3
  from uuid import uuid4
4
4
 
5
5
  from agno.agent import Agent
6
- from agno.media import AudioArtifact, ImageArtifact
6
+ from agno.media import Audio, Image
7
7
  from agno.team.team import Team
8
8
  from agno.tools import Toolkit
9
9
  from agno.tools.function import ToolResult
@@ -149,7 +149,7 @@ class OpenAITools(Toolkit):
149
149
  image_bytes = base64.b64decode(image_base64)
150
150
 
151
151
  # Create ImageArtifact and return in ToolResult
152
- image_artifact = ImageArtifact(
152
+ image_artifact = Image(
153
153
  id=media_id,
154
154
  content=image_bytes, # ← Store as bytes, not encoded string
155
155
  mime_type="image/png",
@@ -176,8 +176,6 @@ class OpenAITools(Toolkit):
176
176
  text_input (str): The text to synthesize into speech.
177
177
  """
178
178
  try:
179
- import base64
180
-
181
179
  response = OpenAIClient(api_key=self.api_key).audio.speech.create(
182
180
  model=self.tts_model,
183
181
  voice=self.tts_voice,
@@ -188,14 +186,11 @@ class OpenAITools(Toolkit):
188
186
  # Get raw audio data for artifact creation before potentially saving
189
187
  audio_data: bytes = response.content
190
188
 
191
- # Base64 encode the audio data
192
- base64_encoded_audio = base64.b64encode(audio_data).decode("utf-8")
193
-
194
189
  # Create AudioArtifact and return in ToolResult
195
190
  media_id = str(uuid4())
196
- audio_artifact = AudioArtifact(
191
+ audio_artifact = Audio(
197
192
  id=media_id,
198
- base64_audio=base64_encoded_audio,
193
+ content=audio_data,
199
194
  mime_type=f"audio/{self.tts_format}",
200
195
  )
201
196
 
agno/tools/opencv.py CHANGED
@@ -4,7 +4,7 @@ from typing import Callable, List
4
4
  from uuid import uuid4
5
5
 
6
6
  from agno.agent import Agent
7
- from agno.media import ImageArtifact, VideoArtifact
7
+ from agno.media import Image, Video
8
8
  from agno.tools import Toolkit
9
9
  from agno.tools.function import ToolResult
10
10
  from agno.utils.log import log_debug, log_error, log_info
@@ -120,7 +120,7 @@ class OpenCVTools(Toolkit):
120
120
  media_id = str(uuid4())
121
121
 
122
122
  # Create ImageArtifact with raw bytes (not base64 encoded)
123
- image_artifact = ImageArtifact(
123
+ image_artifact = Image(
124
124
  id=media_id,
125
125
  content=image_bytes, # Store as raw bytes
126
126
  original_prompt=prompt,
@@ -292,7 +292,7 @@ class OpenCVTools(Toolkit):
292
292
  media_id = str(uuid4())
293
293
 
294
294
  # Create VideoArtifact with base64 encoded content
295
- video_artifact = VideoArtifact(
295
+ video_artifact = Video(
296
296
  id=media_id,
297
297
  content=video_bytes,
298
298
  original_prompt=prompt,