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.
- agno/agent/agent.py +6009 -2874
- agno/api/api.py +2 -0
- agno/api/os.py +1 -1
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +385 -6
- agno/db/dynamo/dynamo.py +388 -81
- agno/db/dynamo/schemas.py +47 -10
- agno/db/dynamo/utils.py +63 -4
- agno/db/firestore/firestore.py +435 -64
- agno/db/firestore/schemas.py +11 -0
- agno/db/firestore/utils.py +102 -4
- agno/db/gcs_json/gcs_json_db.py +384 -42
- agno/db/gcs_json/utils.py +60 -26
- agno/db/in_memory/in_memory_db.py +351 -66
- agno/db/in_memory/utils.py +60 -2
- agno/db/json/json_db.py +339 -48
- agno/db/json/utils.py +60 -26
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +510 -37
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +2036 -0
- agno/db/mongo/mongo.py +653 -76
- agno/db/mongo/schemas.py +13 -0
- agno/db/mongo/utils.py +80 -8
- agno/db/mysql/mysql.py +687 -25
- agno/db/mysql/schemas.py +61 -37
- agno/db/mysql/utils.py +60 -2
- agno/db/postgres/__init__.py +2 -1
- agno/db/postgres/async_postgres.py +2001 -0
- agno/db/postgres/postgres.py +676 -57
- agno/db/postgres/schemas.py +43 -18
- agno/db/postgres/utils.py +164 -2
- agno/db/redis/redis.py +344 -38
- agno/db/redis/schemas.py +18 -0
- agno/db/redis/utils.py +60 -2
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/memory.py +13 -0
- agno/db/singlestore/schemas.py +26 -1
- agno/db/singlestore/singlestore.py +687 -53
- agno/db/singlestore/utils.py +60 -2
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2371 -0
- agno/db/sqlite/schemas.py +24 -0
- agno/db/sqlite/sqlite.py +774 -85
- agno/db/sqlite/utils.py +168 -5
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1361 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +50 -22
- agno/eval/accuracy.py +50 -43
- agno/eval/performance.py +6 -3
- agno/eval/reliability.py +6 -3
- agno/eval/utils.py +33 -16
- agno/exceptions.py +68 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/integrations/discord/client.py +1 -0
- agno/knowledge/chunking/agentic.py +13 -10
- agno/knowledge/chunking/fixed.py +1 -1
- agno/knowledge/chunking/semantic.py +40 -8
- agno/knowledge/chunking/strategy.py +59 -15
- agno/knowledge/embedder/aws_bedrock.py +9 -4
- agno/knowledge/embedder/azure_openai.py +54 -0
- agno/knowledge/embedder/base.py +2 -0
- agno/knowledge/embedder/cohere.py +184 -5
- agno/knowledge/embedder/fastembed.py +1 -1
- agno/knowledge/embedder/google.py +79 -1
- agno/knowledge/embedder/huggingface.py +9 -4
- agno/knowledge/embedder/jina.py +63 -0
- agno/knowledge/embedder/mistral.py +78 -11
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/ollama.py +13 -0
- agno/knowledge/embedder/openai.py +37 -65
- agno/knowledge/embedder/sentence_transformer.py +8 -4
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +69 -16
- agno/knowledge/knowledge.py +595 -187
- agno/knowledge/reader/base.py +9 -2
- agno/knowledge/reader/csv_reader.py +8 -10
- agno/knowledge/reader/docx_reader.py +5 -6
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/json_reader.py +6 -5
- agno/knowledge/reader/markdown_reader.py +13 -13
- agno/knowledge/reader/pdf_reader.py +43 -68
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +51 -6
- agno/knowledge/reader/s3_reader.py +3 -15
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +13 -13
- agno/knowledge/reader/web_search_reader.py +2 -43
- agno/knowledge/reader/website_reader.py +43 -25
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/types.py +9 -0
- agno/knowledge/utils.py +20 -0
- agno/media.py +339 -266
- agno/memory/manager.py +336 -82
- agno/models/aimlapi/aimlapi.py +2 -2
- agno/models/anthropic/claude.py +183 -37
- agno/models/aws/bedrock.py +52 -112
- agno/models/aws/claude.py +33 -1
- agno/models/azure/ai_foundry.py +33 -15
- agno/models/azure/openai_chat.py +25 -8
- agno/models/base.py +1011 -566
- agno/models/cerebras/cerebras.py +19 -13
- agno/models/cerebras/cerebras_openai.py +8 -5
- agno/models/cohere/chat.py +27 -1
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/dashscope.py +1 -0
- agno/models/deepinfra/deepinfra.py +2 -2
- agno/models/deepseek/deepseek.py +2 -2
- agno/models/fireworks/fireworks.py +2 -2
- agno/models/google/gemini.py +110 -37
- agno/models/groq/groq.py +28 -11
- agno/models/huggingface/huggingface.py +2 -1
- agno/models/internlm/internlm.py +2 -2
- agno/models/langdb/langdb.py +4 -4
- agno/models/litellm/chat.py +18 -1
- agno/models/litellm/litellm_openai.py +2 -2
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/message.py +143 -4
- agno/models/meta/llama.py +27 -10
- agno/models/meta/llama_openai.py +5 -17
- agno/models/nebius/nebius.py +6 -6
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/nvidia.py +2 -2
- agno/models/ollama/chat.py +60 -6
- agno/models/openai/chat.py +102 -43
- agno/models/openai/responses.py +103 -106
- agno/models/openrouter/openrouter.py +41 -3
- agno/models/perplexity/perplexity.py +4 -5
- agno/models/portkey/portkey.py +3 -3
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +81 -5
- agno/models/sambanova/sambanova.py +2 -2
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/together.py +2 -2
- agno/models/utils.py +254 -8
- agno/models/vercel/v0.py +2 -2
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +96 -0
- agno/models/vllm/vllm.py +1 -0
- agno/models/xai/xai.py +3 -2
- agno/os/app.py +543 -175
- agno/os/auth.py +24 -14
- agno/os/config.py +1 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/agui.py +23 -7
- agno/os/interfaces/agui/router.py +27 -3
- agno/os/interfaces/agui/utils.py +242 -142
- agno/os/interfaces/base.py +6 -2
- agno/os/interfaces/slack/router.py +81 -23
- agno/os/interfaces/slack/slack.py +29 -14
- agno/os/interfaces/whatsapp/router.py +11 -4
- agno/os/interfaces/whatsapp/whatsapp.py +14 -7
- agno/os/mcp.py +111 -54
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +556 -139
- agno/os/routers/evals/evals.py +71 -34
- agno/os/routers/evals/schemas.py +31 -31
- agno/os/routers/evals/utils.py +6 -5
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +185 -38
- agno/os/routers/knowledge/schemas.py +82 -22
- agno/os/routers/memory/memory.py +158 -53
- agno/os/routers/memory/schemas.py +20 -16
- agno/os/routers/metrics/metrics.py +20 -8
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +499 -38
- agno/os/schema.py +308 -198
- agno/os/utils.py +401 -41
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +3 -1
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +2 -2
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +7 -2
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +266 -112
- agno/run/base.py +53 -24
- agno/run/team.py +252 -111
- agno/run/workflow.py +156 -45
- agno/session/agent.py +105 -89
- agno/session/summary.py +65 -25
- agno/session/team.py +176 -96
- agno/session/workflow.py +406 -40
- agno/team/team.py +3854 -1692
- agno/tools/brightdata.py +3 -3
- agno/tools/cartesia.py +3 -5
- agno/tools/dalle.py +9 -8
- agno/tools/decorator.py +4 -2
- agno/tools/desi_vocal.py +2 -2
- agno/tools/duckduckgo.py +15 -11
- agno/tools/e2b.py +20 -13
- agno/tools/eleven_labs.py +26 -28
- agno/tools/exa.py +21 -16
- agno/tools/fal.py +4 -4
- agno/tools/file.py +153 -23
- agno/tools/file_generation.py +350 -0
- agno/tools/firecrawl.py +4 -4
- agno/tools/function.py +257 -37
- agno/tools/giphy.py +2 -2
- agno/tools/gmail.py +238 -14
- agno/tools/google_drive.py +270 -0
- agno/tools/googlecalendar.py +36 -8
- agno/tools/googlesheets.py +20 -5
- agno/tools/jira.py +20 -0
- agno/tools/knowledge.py +3 -3
- agno/tools/lumalab.py +3 -3
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +11 -17
- agno/tools/memori.py +1 -53
- agno/tools/memory.py +419 -0
- agno/tools/models/azure_openai.py +2 -2
- agno/tools/models/gemini.py +3 -3
- agno/tools/models/groq.py +3 -5
- agno/tools/models/nebius.py +7 -7
- agno/tools/models_labs.py +25 -15
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +4 -9
- agno/tools/opencv.py +3 -3
- agno/tools/parallel.py +314 -0
- agno/tools/replicate.py +7 -7
- agno/tools/scrapegraph.py +58 -31
- agno/tools/searxng.py +2 -2
- agno/tools/serper.py +2 -2
- agno/tools/slack.py +18 -3
- agno/tools/spider.py +2 -2
- agno/tools/tavily.py +146 -0
- agno/tools/whatsapp.py +1 -1
- agno/tools/workflow.py +278 -0
- agno/tools/yfinance.py +12 -11
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +27 -0
- agno/utils/common.py +90 -1
- agno/utils/events.py +222 -7
- agno/utils/gemini.py +181 -23
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +111 -0
- agno/utils/knowledge.py +12 -5
- agno/utils/log.py +1 -0
- agno/utils/mcp.py +95 -5
- agno/utils/media.py +188 -10
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +60 -0
- agno/utils/models/claude.py +40 -11
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/print_response/agent.py +105 -21
- agno/utils/print_response/team.py +103 -38
- agno/utils/print_response/workflow.py +251 -34
- agno/utils/reasoning.py +22 -1
- agno/utils/serialize.py +32 -0
- agno/utils/streamlit.py +16 -10
- agno/utils/string.py +41 -0
- agno/utils/team.py +98 -9
- agno/utils/tools.py +1 -1
- agno/vectordb/base.py +23 -4
- agno/vectordb/cassandra/cassandra.py +65 -9
- agno/vectordb/chroma/chromadb.py +182 -38
- agno/vectordb/clickhouse/clickhousedb.py +64 -11
- agno/vectordb/couchbase/couchbase.py +105 -10
- agno/vectordb/lancedb/lance_db.py +183 -135
- agno/vectordb/langchaindb/langchaindb.py +25 -7
- agno/vectordb/lightrag/lightrag.py +17 -3
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +46 -7
- agno/vectordb/milvus/milvus.py +126 -9
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/mongodb/mongodb.py +112 -7
- agno/vectordb/pgvector/pgvector.py +142 -21
- agno/vectordb/pineconedb/pineconedb.py +80 -8
- agno/vectordb/qdrant/qdrant.py +125 -39
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/singlestore/singlestore.py +111 -25
- agno/vectordb/surrealdb/surrealdb.py +31 -5
- agno/vectordb/upstashdb/upstashdb.py +76 -8
- agno/vectordb/weaviate/weaviate.py +86 -15
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +112 -18
- agno/workflow/loop.py +69 -10
- agno/workflow/parallel.py +266 -118
- agno/workflow/router.py +110 -17
- agno/workflow/step.py +645 -136
- agno/workflow/steps.py +65 -6
- agno/workflow/types.py +71 -33
- agno/workflow/workflow.py +2113 -300
- agno-2.3.0.dist-info/METADATA +618 -0
- agno-2.3.0.dist-info/RECORD +577 -0
- agno-2.3.0.dist-info/licenses/LICENSE +201 -0
- agno/knowledge/reader/url_reader.py +0 -128
- agno/tools/googlesearch.py +0 -98
- agno/tools/mcp.py +0 -610
- agno/utils/models/aws_claude.py +0 -170
- agno-2.0.0rc2.dist-info/METADATA +0 -355
- agno-2.0.0rc2.dist-info/RECORD +0 -515
- agno-2.0.0rc2.dist-info/licenses/LICENSE +0 -375
- {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
- {agno-2.0.0rc2.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
agno/tools/brightdata.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Any, Dict, List, Optional
|
|
|
5
5
|
from uuid import uuid4
|
|
6
6
|
|
|
7
7
|
from agno.agent import Agent
|
|
8
|
-
from agno.media import
|
|
8
|
+
from agno.media import Image
|
|
9
9
|
from agno.tools import Toolkit
|
|
10
10
|
from agno.tools.function import ToolResult
|
|
11
11
|
from agno.utils.log import log_debug, log_error, log_info
|
|
@@ -158,8 +158,8 @@ class BrightDataTools(Toolkit):
|
|
|
158
158
|
|
|
159
159
|
media_id = str(uuid4())
|
|
160
160
|
|
|
161
|
-
# Create
|
|
162
|
-
image_artifact =
|
|
161
|
+
# Create Image for the screenshot
|
|
162
|
+
image_artifact = Image(
|
|
163
163
|
id=media_id,
|
|
164
164
|
content=base64_encoded_image.encode("utf-8"),
|
|
165
165
|
mime_type="image/png",
|
agno/tools/cartesia.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from base64 import b64encode
|
|
3
2
|
from os import getenv
|
|
4
3
|
from typing import Any, Dict, List, Optional, Union
|
|
5
4
|
from uuid import uuid4
|
|
6
5
|
|
|
7
6
|
from agno.agent import Agent
|
|
8
|
-
from agno.media import
|
|
7
|
+
from agno.media import Audio
|
|
9
8
|
from agno.team.team import Team
|
|
10
9
|
from agno.tools import Toolkit
|
|
11
10
|
from agno.tools.function import ToolResult
|
|
@@ -170,12 +169,11 @@ class CartesiaTools(Toolkit):
|
|
|
170
169
|
|
|
171
170
|
audio_iterator = self.client.tts.bytes(**params)
|
|
172
171
|
audio_data = b"".join(chunk for chunk in audio_iterator)
|
|
173
|
-
base64_audio = b64encode(audio_data).decode("utf-8")
|
|
174
172
|
|
|
175
173
|
# Create AudioArtifact
|
|
176
|
-
audio_artifact =
|
|
174
|
+
audio_artifact = Audio(
|
|
177
175
|
id=str(uuid4()),
|
|
178
|
-
|
|
176
|
+
content=audio_data,
|
|
179
177
|
mime_type=mime_type, # Hardcoded to audio/mpeg
|
|
180
178
|
)
|
|
181
179
|
|
agno/tools/dalle.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
from os import getenv
|
|
2
|
-
from typing import Any, List, Literal, Optional
|
|
2
|
+
from typing import Any, List, Literal, Optional
|
|
3
3
|
from uuid import uuid4
|
|
4
4
|
|
|
5
|
-
from agno.
|
|
6
|
-
from agno.media import ImageArtifact
|
|
7
|
-
from agno.team.team import Team
|
|
5
|
+
from agno.media import Image
|
|
8
6
|
from agno.tools import Toolkit
|
|
9
7
|
from agno.tools.function import ToolResult
|
|
10
8
|
from agno.utils.log import log_debug, logger
|
|
@@ -64,7 +62,7 @@ class DalleTools(Toolkit):
|
|
|
64
62
|
# - Add support for saving images
|
|
65
63
|
# - Add support for editing images
|
|
66
64
|
|
|
67
|
-
def create_image(self,
|
|
65
|
+
def create_image(self, prompt: str) -> ToolResult:
|
|
68
66
|
"""Use this function to generate an image for a prompt.
|
|
69
67
|
|
|
70
68
|
Args:
|
|
@@ -94,10 +92,13 @@ class DalleTools(Toolkit):
|
|
|
94
92
|
if response.data:
|
|
95
93
|
for img in response.data:
|
|
96
94
|
if img.url:
|
|
97
|
-
|
|
98
|
-
id=str(uuid4()),
|
|
95
|
+
image = Image(
|
|
96
|
+
id=str(uuid4()),
|
|
97
|
+
url=img.url,
|
|
98
|
+
original_prompt=prompt,
|
|
99
|
+
revised_prompt=img.revised_prompt,
|
|
99
100
|
)
|
|
100
|
-
generated_images.append(
|
|
101
|
+
generated_images.append(image)
|
|
101
102
|
response_str += f"Image has been generated at the URL {img.url}\n"
|
|
102
103
|
|
|
103
104
|
return ToolResult(
|
agno/tools/decorator.py
CHANGED
|
@@ -250,8 +250,10 @@ def tool(*args, **kwargs) -> Union[Function, Callable[[F], Function]]:
|
|
|
250
250
|
if kwargs.get("stop_after_tool_call") is True:
|
|
251
251
|
if "show_result" not in kwargs or kwargs.get("show_result") is None:
|
|
252
252
|
tool_config["show_result"] = True
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
function = Function(**tool_config)
|
|
254
|
+
# Determine parameters for the function
|
|
255
|
+
function.process_entrypoint()
|
|
256
|
+
return function
|
|
255
257
|
|
|
256
258
|
# Handle both @tool and @tool() cases
|
|
257
259
|
if len(args) == 1 and callable(args[0]) and not kwargs:
|
agno/tools/desi_vocal.py
CHANGED
|
@@ -5,7 +5,7 @@ from uuid import uuid4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
7
|
from agno.agent import Agent
|
|
8
|
-
from agno.media import
|
|
8
|
+
from agno.media import Audio
|
|
9
9
|
from agno.team.team import Team
|
|
10
10
|
from agno.tools import Toolkit
|
|
11
11
|
from agno.tools.function import ToolResult
|
|
@@ -97,7 +97,7 @@ class DesiVocalTools(Toolkit):
|
|
|
97
97
|
response_json = response.json()
|
|
98
98
|
audio_url = response_json["s3_path"]
|
|
99
99
|
|
|
100
|
-
audio_artifact =
|
|
100
|
+
audio_artifact = Audio(id=str(uuid4()), url=audio_url)
|
|
101
101
|
|
|
102
102
|
return ToolResult(
|
|
103
103
|
content=f"Audio generated successfully: {audio_url}",
|
agno/tools/duckduckgo.py
CHANGED
|
@@ -12,14 +12,16 @@ except ImportError:
|
|
|
12
12
|
|
|
13
13
|
class DuckDuckGoTools(Toolkit):
|
|
14
14
|
"""
|
|
15
|
-
DuckDuckGo is a toolkit for searching DuckDuckGo easily.
|
|
15
|
+
DuckDuckGo is a toolkit for searching using DuckDuckGo easily.
|
|
16
|
+
It uses the meta-search library DDGS, so it also has access to other backends.
|
|
16
17
|
Args:
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
enable_search (bool): Enable DDGS search function.
|
|
19
|
+
enable_news (bool): Enable DDGS news function.
|
|
19
20
|
modifier (Optional[str]): A modifier to be used in the search request.
|
|
20
21
|
fixed_max_results (Optional[int]): A fixed number of maximum results.
|
|
21
22
|
proxy (Optional[str]): Proxy to be used in the search request.
|
|
22
23
|
timeout (Optional[int]): The maximum number of seconds to wait for a response.
|
|
24
|
+
backend (Optional[str]): The backend to be used in the search request.
|
|
23
25
|
|
|
24
26
|
"""
|
|
25
27
|
|
|
@@ -28,6 +30,7 @@ class DuckDuckGoTools(Toolkit):
|
|
|
28
30
|
enable_search: bool = True,
|
|
29
31
|
enable_news: bool = True,
|
|
30
32
|
all: bool = False,
|
|
33
|
+
backend: str = "duckduckgo",
|
|
31
34
|
modifier: Optional[str] = None,
|
|
32
35
|
fixed_max_results: Optional[int] = None,
|
|
33
36
|
proxy: Optional[str] = None,
|
|
@@ -40,6 +43,7 @@ class DuckDuckGoTools(Toolkit):
|
|
|
40
43
|
self.fixed_max_results: Optional[int] = fixed_max_results
|
|
41
44
|
self.modifier: Optional[str] = modifier
|
|
42
45
|
self.verify_ssl: bool = verify_ssl
|
|
46
|
+
self.backend: str = backend
|
|
43
47
|
|
|
44
48
|
tools: List[Any] = []
|
|
45
49
|
if all or enable_search:
|
|
@@ -50,38 +54,38 @@ class DuckDuckGoTools(Toolkit):
|
|
|
50
54
|
super().__init__(name="duckduckgo", tools=tools, **kwargs)
|
|
51
55
|
|
|
52
56
|
def duckduckgo_search(self, query: str, max_results: int = 5) -> str:
|
|
53
|
-
"""Use this function to search
|
|
57
|
+
"""Use this function to search DDGS for a query.
|
|
54
58
|
|
|
55
59
|
Args:
|
|
56
60
|
query(str): The query to search for.
|
|
57
61
|
max_results (optional, default=5): The maximum number of results to return.
|
|
58
62
|
|
|
59
63
|
Returns:
|
|
60
|
-
The result from
|
|
64
|
+
The result from DDGS.
|
|
61
65
|
"""
|
|
62
66
|
actual_max_results = self.fixed_max_results or max_results
|
|
63
67
|
search_query = f"{self.modifier} {query}" if self.modifier else query
|
|
64
68
|
|
|
65
|
-
log_debug(f"Searching DDG for: {search_query}")
|
|
69
|
+
log_debug(f"Searching DDG for: {search_query} using backend: {self.backend}")
|
|
66
70
|
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
67
|
-
results = ddgs.text(query=search_query, max_results=actual_max_results)
|
|
71
|
+
results = ddgs.text(query=search_query, max_results=actual_max_results, backend=self.backend)
|
|
68
72
|
|
|
69
73
|
return json.dumps(results, indent=2)
|
|
70
74
|
|
|
71
75
|
def duckduckgo_news(self, query: str, max_results: int = 5) -> str:
|
|
72
|
-
"""Use this function to get the latest news from
|
|
76
|
+
"""Use this function to get the latest news from DDGS.
|
|
73
77
|
|
|
74
78
|
Args:
|
|
75
79
|
query(str): The query to search for.
|
|
76
80
|
max_results (optional, default=5): The maximum number of results to return.
|
|
77
81
|
|
|
78
82
|
Returns:
|
|
79
|
-
The latest news from
|
|
83
|
+
The latest news from DDGS.
|
|
80
84
|
"""
|
|
81
85
|
actual_max_results = self.fixed_max_results or max_results
|
|
82
86
|
|
|
83
|
-
log_debug(f"Searching DDG news for: {query}")
|
|
87
|
+
log_debug(f"Searching DDG news for: {query} using backend: {self.backend}")
|
|
84
88
|
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
85
|
-
results = ddgs.news(query=query, max_results=actual_max_results)
|
|
89
|
+
results = ddgs.news(query=query, max_results=actual_max_results, backend=self.backend)
|
|
86
90
|
|
|
87
91
|
return json.dumps(results, indent=2)
|
agno/tools/e2b.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import Any, Callable, Dict, List, Optional, Union
|
|
|
8
8
|
from uuid import uuid4
|
|
9
9
|
|
|
10
10
|
from agno.agent import Agent
|
|
11
|
-
from agno.media import
|
|
11
|
+
from agno.media import Image
|
|
12
12
|
from agno.team.team import Team
|
|
13
13
|
from agno.tools import Toolkit
|
|
14
14
|
from agno.tools.function import ToolResult
|
|
@@ -161,7 +161,7 @@ class E2BTools(Toolkit):
|
|
|
161
161
|
self, agent: Union[Agent, Team], result_index: int = 0, output_path: Optional[str] = None
|
|
162
162
|
) -> ToolResult:
|
|
163
163
|
"""
|
|
164
|
-
Add a PNG image result from the last code execution as an
|
|
164
|
+
Add a PNG image result from the last code execution as an Image object.
|
|
165
165
|
|
|
166
166
|
Args:
|
|
167
167
|
agent: The agent to add the image artifact to
|
|
@@ -205,9 +205,9 @@ class E2BTools(Toolkit):
|
|
|
205
205
|
# Generate a file:// URL for the temp file
|
|
206
206
|
file_url = f"file://{temp_path}"
|
|
207
207
|
|
|
208
|
-
# Create
|
|
208
|
+
# Create Image object
|
|
209
209
|
image_id = str(uuid4())
|
|
210
|
-
image_artifact =
|
|
210
|
+
image_artifact = Image(
|
|
211
211
|
id=image_id, url=file_url, original_prompt=f"Generated from code execution result {result_index}"
|
|
212
212
|
)
|
|
213
213
|
|
|
@@ -292,9 +292,9 @@ class E2BTools(Toolkit):
|
|
|
292
292
|
# Generate a file:// URL for the temp file
|
|
293
293
|
file_url = f"file://{temp_path}"
|
|
294
294
|
|
|
295
|
-
# Create
|
|
295
|
+
# Create Image object
|
|
296
296
|
image_id = str(uuid4())
|
|
297
|
-
image_artifact =
|
|
297
|
+
image_artifact = Image(
|
|
298
298
|
id=image_id, url=file_url, original_prompt=f"Interactive {chart_type} chart from code execution"
|
|
299
299
|
)
|
|
300
300
|
|
|
@@ -464,7 +464,7 @@ class E2BTools(Toolkit):
|
|
|
464
464
|
|
|
465
465
|
result = f"Contents of {directory_path}:\n"
|
|
466
466
|
for file in files:
|
|
467
|
-
file_type = "Directory" if file.
|
|
467
|
+
file_type = "Directory" if file.type == "directory" else "File"
|
|
468
468
|
size = f"{file.size} bytes" if file.size is not None else "Unknown size"
|
|
469
469
|
result += f"- {file.name} ({file_type}, {size})\n"
|
|
470
470
|
|
|
@@ -486,12 +486,19 @@ class E2BTools(Toolkit):
|
|
|
486
486
|
try:
|
|
487
487
|
content = self.sandbox.files.read(file_path)
|
|
488
488
|
|
|
489
|
-
#
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
489
|
+
# Check if content is already a string or if it's bytes that need decoding
|
|
490
|
+
if isinstance(content, str):
|
|
491
|
+
return content
|
|
492
|
+
elif isinstance(content, bytes):
|
|
493
|
+
# Try to decode as text if encoding is provided
|
|
494
|
+
try:
|
|
495
|
+
text_content = content.decode(encoding)
|
|
496
|
+
return text_content
|
|
497
|
+
except UnicodeDecodeError:
|
|
498
|
+
return f"File read successfully but contains binary data ({len(content)} bytes). Use download_file_from_sandbox to save it."
|
|
499
|
+
else:
|
|
500
|
+
# Handle unexpected content type
|
|
501
|
+
return f"Unexpected content type: {type(content)}. Expected str or bytes."
|
|
495
502
|
|
|
496
503
|
except Exception as e:
|
|
497
504
|
return json.dumps({"status": "error", "message": f"Error reading file: {str(e)}"})
|
agno/tools/eleven_labs.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from base64 import b64encode
|
|
2
1
|
from io import BytesIO
|
|
3
2
|
from os import getenv, path
|
|
4
3
|
from pathlib import Path
|
|
@@ -6,11 +5,11 @@ from typing import Any, Iterator, List, Literal, Optional, Union
|
|
|
6
5
|
from uuid import uuid4
|
|
7
6
|
|
|
8
7
|
from agno.agent import Agent
|
|
9
|
-
from agno.media import
|
|
8
|
+
from agno.media import Audio
|
|
10
9
|
from agno.team.team import Team
|
|
11
10
|
from agno.tools import Toolkit
|
|
12
11
|
from agno.tools.function import ToolResult
|
|
13
|
-
from agno.utils.log import
|
|
12
|
+
from agno.utils.log import log_error, log_info
|
|
14
13
|
|
|
15
14
|
try:
|
|
16
15
|
from elevenlabs import ElevenLabs # type: ignore
|
|
@@ -48,7 +47,7 @@ class ElevenLabsTools(Toolkit):
|
|
|
48
47
|
):
|
|
49
48
|
self.api_key = api_key or getenv("ELEVEN_LABS_API_KEY")
|
|
50
49
|
if not self.api_key:
|
|
51
|
-
|
|
50
|
+
log_error("ELEVEN_LABS_API_KEY not set. Please set the ELEVEN_LABS_API_KEY environment variable.")
|
|
52
51
|
|
|
53
52
|
self.target_directory = target_directory
|
|
54
53
|
self.voice_id = voice_id
|
|
@@ -73,7 +72,7 @@ class ElevenLabsTools(Toolkit):
|
|
|
73
72
|
|
|
74
73
|
def get_voices(self) -> str:
|
|
75
74
|
"""
|
|
76
|
-
|
|
75
|
+
Get all the voices available.
|
|
77
76
|
|
|
78
77
|
Returns:
|
|
79
78
|
result (list): A list of voices that have an ID, name and description.
|
|
@@ -94,20 +93,19 @@ class ElevenLabsTools(Toolkit):
|
|
|
94
93
|
return str(response)
|
|
95
94
|
|
|
96
95
|
except Exception as e:
|
|
97
|
-
|
|
96
|
+
log_error(f"Failed to fetch voices: {e}")
|
|
98
97
|
return f"Error: {e}"
|
|
99
98
|
|
|
100
|
-
def _process_audio(self, audio_generator: Iterator[bytes]) ->
|
|
101
|
-
# Step 1: Write audio data to BytesIO
|
|
99
|
+
def _process_audio(self, audio_generator: Iterator[bytes]) -> bytes:
|
|
102
100
|
audio_bytes = BytesIO()
|
|
103
101
|
for chunk in audio_generator:
|
|
104
102
|
audio_bytes.write(chunk)
|
|
105
|
-
audio_bytes.seek(0) # Rewind the stream
|
|
106
103
|
|
|
107
|
-
#
|
|
108
|
-
|
|
104
|
+
# Read bytes
|
|
105
|
+
audio_bytes.seek(0)
|
|
106
|
+
audio_data = audio_bytes.read()
|
|
109
107
|
|
|
110
|
-
#
|
|
108
|
+
# Save to disk if target_directory exists
|
|
111
109
|
if self.target_directory:
|
|
112
110
|
# Determine file extension based on output format
|
|
113
111
|
if self.output_format.startswith("mp3"):
|
|
@@ -122,19 +120,19 @@ class ElevenLabsTools(Toolkit):
|
|
|
122
120
|
output_filename = f"{uuid4()}.{extension}"
|
|
123
121
|
output_path = path.join(self.target_directory, output_filename)
|
|
124
122
|
|
|
125
|
-
# Write from BytesIO to disk
|
|
126
|
-
audio_bytes.seek(0) # Reset the BytesIO stream again
|
|
127
123
|
with open(output_path, "wb") as f:
|
|
128
|
-
f.write(
|
|
124
|
+
f.write(audio_data)
|
|
129
125
|
|
|
130
|
-
|
|
126
|
+
log_info(f"Audio saved to: {output_path}")
|
|
127
|
+
|
|
128
|
+
return audio_data
|
|
131
129
|
|
|
132
130
|
def generate_sound_effect(self, prompt: str, duration_seconds: Optional[float] = None) -> ToolResult:
|
|
133
131
|
"""
|
|
134
|
-
|
|
132
|
+
Generate a sound effect from a text description.
|
|
135
133
|
|
|
136
134
|
Args:
|
|
137
|
-
prompt (str):
|
|
135
|
+
prompt (str): Description of the sound effect
|
|
138
136
|
duration_seconds (Optional[float]): Duration in seconds to generate audio from. Has to be between 0.5 and 22.
|
|
139
137
|
Returns:
|
|
140
138
|
ToolResult: A ToolResult containing the generated audio or error message.
|
|
@@ -144,27 +142,27 @@ class ElevenLabsTools(Toolkit):
|
|
|
144
142
|
text=prompt, duration_seconds=duration_seconds
|
|
145
143
|
)
|
|
146
144
|
|
|
147
|
-
|
|
145
|
+
audio_data = self._process_audio(audio_generator)
|
|
148
146
|
|
|
149
147
|
# Create AudioArtifact
|
|
150
|
-
audio_artifact =
|
|
148
|
+
audio_artifact = Audio(
|
|
151
149
|
id=str(uuid4()),
|
|
152
|
-
|
|
150
|
+
content=audio_data,
|
|
153
151
|
mime_type="audio/mpeg",
|
|
154
152
|
)
|
|
155
153
|
|
|
156
154
|
return ToolResult(
|
|
157
|
-
content="
|
|
155
|
+
content="Sound effect generated successfully",
|
|
158
156
|
audios=[audio_artifact],
|
|
159
157
|
)
|
|
160
158
|
|
|
161
159
|
except Exception as e:
|
|
162
|
-
|
|
160
|
+
log_error(f"Failed to generate sound effect: {e}")
|
|
163
161
|
return ToolResult(content=f"Error: {e}")
|
|
164
162
|
|
|
165
163
|
def text_to_speech(self, agent: Union[Agent, Team], prompt: str) -> ToolResult:
|
|
166
164
|
"""
|
|
167
|
-
|
|
165
|
+
Convert text to speech.
|
|
168
166
|
|
|
169
167
|
Args:
|
|
170
168
|
prompt (str): Text to generate audio from.
|
|
@@ -179,12 +177,12 @@ class ElevenLabsTools(Toolkit):
|
|
|
179
177
|
output_format=self.output_format,
|
|
180
178
|
)
|
|
181
179
|
|
|
182
|
-
|
|
180
|
+
audio_data = self._process_audio(audio_generator)
|
|
183
181
|
|
|
184
182
|
# Create AudioArtifact
|
|
185
|
-
audio_artifact =
|
|
183
|
+
audio_artifact = Audio(
|
|
186
184
|
id=str(uuid4()),
|
|
187
|
-
|
|
185
|
+
content=audio_data,
|
|
188
186
|
mime_type="audio/mpeg",
|
|
189
187
|
)
|
|
190
188
|
|
|
@@ -194,5 +192,5 @@ class ElevenLabsTools(Toolkit):
|
|
|
194
192
|
)
|
|
195
193
|
|
|
196
194
|
except Exception as e:
|
|
197
|
-
|
|
195
|
+
log_error(f"Failed to generate audio: {e}")
|
|
198
196
|
return ToolResult(content=f"Error: {e}")
|
agno/tools/exa.py
CHANGED
|
@@ -27,14 +27,14 @@ class ExaTools(Toolkit):
|
|
|
27
27
|
all (bool): Enable all tools. Overrides individual flags when True. Default is False.
|
|
28
28
|
text (bool): Retrieve text content from results. Default is True.
|
|
29
29
|
text_length_limit (int): Max length of text content per result. Default is 1000.
|
|
30
|
-
highlights (bool): Include highlighted snippets.
|
|
30
|
+
highlights (bool): Include highlighted snippets. Deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.
|
|
31
31
|
api_key (Optional[str]): Exa API key. Retrieved from `EXA_API_KEY` env variable if not provided.
|
|
32
32
|
num_results (Optional[int]): Default number of search results. Overrides individual searches if set.
|
|
33
33
|
start_crawl_date (Optional[str]): Include results crawled on/after this date (`YYYY-MM-DD`).
|
|
34
34
|
end_crawl_date (Optional[str]): Include results crawled on/before this date (`YYYY-MM-DD`).
|
|
35
35
|
start_published_date (Optional[str]): Include results published on/after this date (`YYYY-MM-DD`).
|
|
36
36
|
end_published_date (Optional[str]): Include results published on/before this date (`YYYY-MM-DD`).
|
|
37
|
-
use_autoprompt (Optional[bool]): Enable autoprompt features in queries.
|
|
37
|
+
use_autoprompt (Optional[bool]): Enable autoprompt features in queries. Deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.
|
|
38
38
|
type (Optional[str]): Specify content type (e.g., article, blog, video).
|
|
39
39
|
category (Optional[str]): Filter results by category. Options are "company", "research paper", "news", "pdf", "github", "tweet", "personal site", "linkedin profile", "financial report".
|
|
40
40
|
include_domains (Optional[List[str]]): Restrict results to these domains.
|
|
@@ -54,7 +54,7 @@ class ExaTools(Toolkit):
|
|
|
54
54
|
all: bool = False,
|
|
55
55
|
text: bool = True,
|
|
56
56
|
text_length_limit: int = 1000,
|
|
57
|
-
highlights: bool =
|
|
57
|
+
highlights: Optional[bool] = None, # Deprecated
|
|
58
58
|
summary: bool = False,
|
|
59
59
|
api_key: Optional[str] = None,
|
|
60
60
|
num_results: Optional[int] = None,
|
|
@@ -84,7 +84,24 @@ class ExaTools(Toolkit):
|
|
|
84
84
|
|
|
85
85
|
self.text: bool = text
|
|
86
86
|
self.text_length_limit: int = text_length_limit
|
|
87
|
-
|
|
87
|
+
|
|
88
|
+
if highlights:
|
|
89
|
+
import warnings
|
|
90
|
+
|
|
91
|
+
warnings.warn(
|
|
92
|
+
"The 'highlights' parameter is deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.",
|
|
93
|
+
DeprecationWarning,
|
|
94
|
+
stacklevel=2,
|
|
95
|
+
)
|
|
96
|
+
if use_autoprompt:
|
|
97
|
+
import warnings
|
|
98
|
+
|
|
99
|
+
warnings.warn(
|
|
100
|
+
"The 'use_autoprompt' parameter is deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.",
|
|
101
|
+
DeprecationWarning,
|
|
102
|
+
stacklevel=2,
|
|
103
|
+
)
|
|
104
|
+
|
|
88
105
|
self.summary: bool = summary
|
|
89
106
|
self.num_results: Optional[int] = num_results
|
|
90
107
|
self.livecrawl: str = livecrawl
|
|
@@ -92,7 +109,6 @@ class ExaTools(Toolkit):
|
|
|
92
109
|
self.end_crawl_date: Optional[str] = end_crawl_date
|
|
93
110
|
self.start_published_date: Optional[str] = start_published_date
|
|
94
111
|
self.end_published_date: Optional[str] = end_published_date
|
|
95
|
-
self.use_autoprompt: Optional[bool] = use_autoprompt
|
|
96
112
|
self.type: Optional[str] = type
|
|
97
113
|
self.category: Optional[str] = category
|
|
98
114
|
self.include_domains: Optional[List[str]] = include_domains
|
|
@@ -140,13 +156,6 @@ class ExaTools(Toolkit):
|
|
|
140
156
|
if self.text_length_limit:
|
|
141
157
|
_text = _text[: self.text_length_limit]
|
|
142
158
|
result_dict["text"] = _text
|
|
143
|
-
if self.highlights:
|
|
144
|
-
try:
|
|
145
|
-
if result.highlights: # type: ignore
|
|
146
|
-
result_dict["highlights"] = result.highlights # type: ignore
|
|
147
|
-
except Exception as e:
|
|
148
|
-
log_debug(f"Failed to get highlights {e}")
|
|
149
|
-
result_dict["highlights"] = f"Failed to get highlights {e}"
|
|
150
159
|
exa_results_parsed.append(result_dict)
|
|
151
160
|
return json.dumps(exa_results_parsed, indent=4, ensure_ascii=False)
|
|
152
161
|
|
|
@@ -168,14 +177,12 @@ class ExaTools(Toolkit):
|
|
|
168
177
|
log_info(f"Searching exa for: {query}")
|
|
169
178
|
search_kwargs: Dict[str, Any] = {
|
|
170
179
|
"text": self.text,
|
|
171
|
-
"highlights": self.highlights,
|
|
172
180
|
"summary": self.summary,
|
|
173
181
|
"num_results": self.num_results or num_results,
|
|
174
182
|
"start_crawl_date": self.start_crawl_date,
|
|
175
183
|
"end_crawl_date": self.end_crawl_date,
|
|
176
184
|
"start_published_date": self.start_published_date,
|
|
177
185
|
"end_published_date": self.end_published_date,
|
|
178
|
-
"use_autoprompt": self.use_autoprompt,
|
|
179
186
|
"type": self.type,
|
|
180
187
|
"category": self.category or category, # Prefer a user-set category
|
|
181
188
|
"include_domains": self.include_domains,
|
|
@@ -212,7 +219,6 @@ class ExaTools(Toolkit):
|
|
|
212
219
|
|
|
213
220
|
query_kwargs: Dict[str, Any] = {
|
|
214
221
|
"text": self.text,
|
|
215
|
-
"highlights": self.highlights,
|
|
216
222
|
"summary": self.summary,
|
|
217
223
|
}
|
|
218
224
|
|
|
@@ -249,7 +255,6 @@ class ExaTools(Toolkit):
|
|
|
249
255
|
|
|
250
256
|
query_kwargs: Dict[str, Any] = {
|
|
251
257
|
"text": self.text,
|
|
252
|
-
"highlights": self.highlights,
|
|
253
258
|
"summary": self.summary,
|
|
254
259
|
"include_domains": self.include_domains,
|
|
255
260
|
"exclude_domains": self.exclude_domains,
|
agno/tools/fal.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Optional, Union
|
|
|
7
7
|
from uuid import uuid4
|
|
8
8
|
|
|
9
9
|
from agno.agent import Agent
|
|
10
|
-
from agno.media import
|
|
10
|
+
from agno.media import Image, Video
|
|
11
11
|
from agno.team.team import Team
|
|
12
12
|
from agno.tools import Toolkit
|
|
13
13
|
from agno.tools.function import ToolResult
|
|
@@ -72,14 +72,14 @@ class FalTools(Toolkit):
|
|
|
72
72
|
|
|
73
73
|
if "image" in result:
|
|
74
74
|
url = result.get("image", {}).get("url", "")
|
|
75
|
-
image_artifact =
|
|
75
|
+
image_artifact = Image(
|
|
76
76
|
id=media_id,
|
|
77
77
|
url=url,
|
|
78
78
|
)
|
|
79
79
|
return ToolResult(content=f"Image generated successfully at {url}", images=[image_artifact])
|
|
80
80
|
elif "video" in result:
|
|
81
81
|
url = result.get("video", {}).get("url", "")
|
|
82
|
-
video_artifact =
|
|
82
|
+
video_artifact = Video(
|
|
83
83
|
id=media_id,
|
|
84
84
|
url=url,
|
|
85
85
|
)
|
|
@@ -115,7 +115,7 @@ class FalTools(Toolkit):
|
|
|
115
115
|
)
|
|
116
116
|
url = result.get("images", [{}])[0].get("url", "")
|
|
117
117
|
media_id = str(uuid4())
|
|
118
|
-
image_artifact =
|
|
118
|
+
image_artifact = Image(
|
|
119
119
|
id=media_id,
|
|
120
120
|
url=url,
|
|
121
121
|
)
|