agno 2.2.13__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/__init__.py +8 -0
- agno/agent/__init__.py +51 -0
- agno/agent/agent.py +10405 -0
- agno/api/__init__.py +0 -0
- agno/api/agent.py +28 -0
- agno/api/api.py +40 -0
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +13 -0
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +16 -0
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/response.py +6 -0
- agno/api/schemas/team.py +16 -0
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +30 -0
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +598 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2042 -0
- agno/db/dynamo/schemas.py +314 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1795 -0
- agno/db/firestore/schemas.py +140 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1335 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1160 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1328 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/__init__.py +0 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2026 -0
- agno/db/mongo/mongo.py +1982 -0
- agno/db/mongo/schemas.py +87 -0
- agno/db/mongo/utils.py +259 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +2308 -0
- agno/db/mysql/schemas.py +138 -0
- agno/db/mysql/utils.py +355 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +1927 -0
- agno/db/postgres/postgres.py +2260 -0
- agno/db/postgres/schemas.py +139 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1660 -0
- agno/db/redis/schemas.py +123 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/schemas/metrics.py +0 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +130 -0
- agno/db/singlestore/singlestore.py +2272 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2293 -0
- agno/db/sqlite/schemas.py +133 -0
- agno/db/sqlite/sqlite.py +2288 -0
- agno/db/sqlite/utils.py +431 -0
- 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 +1353 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +116 -0
- agno/debug.py +18 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +834 -0
- agno/eval/performance.py +773 -0
- agno/eval/reliability.py +306 -0
- agno/eval/utils.py +119 -0
- agno/exceptions.py +161 -0
- 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/__init__.py +0 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -0
- agno/knowledge/chunking/__init__.py +0 -0
- agno/knowledge/chunking/agentic.py +79 -0
- agno/knowledge/chunking/document.py +91 -0
- agno/knowledge/chunking/fixed.py +57 -0
- agno/knowledge/chunking/markdown.py +151 -0
- agno/knowledge/chunking/recursive.py +63 -0
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +86 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/knowledge/document/base.py +58 -0
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/knowledge/embedder/base.py +23 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/knowledge/embedder/fireworks.py +13 -0
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/knowledge/embedder/together.py +13 -0
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +1988 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +166 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +87 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +115 -0
- agno/knowledge/reader/web_search_reader.py +372 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/__init__.py +0 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/knowledge/reranker/base.py +14 -0
- agno/knowledge/reranker/cohere.py +64 -0
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +189 -0
- agno/media.py +462 -0
- agno/memory/__init__.py +3 -0
- agno/memory/manager.py +1327 -0
- agno/models/__init__.py +0 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +45 -0
- agno/models/anthropic/__init__.py +5 -0
- agno/models/anthropic/claude.py +757 -0
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +701 -0
- agno/models/aws/claude.py +378 -0
- agno/models/azure/__init__.py +18 -0
- agno/models/azure/ai_foundry.py +485 -0
- agno/models/azure/openai_chat.py +131 -0
- agno/models/base.py +2175 -0
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +501 -0
- agno/models/cerebras/cerebras_openai.py +112 -0
- agno/models/cohere/__init__.py +5 -0
- agno/models/cohere/chat.py +389 -0
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +91 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +28 -0
- agno/models/deepseek/__init__.py +5 -0
- agno/models/deepseek/deepseek.py +61 -0
- agno/models/defaults.py +1 -0
- agno/models/fireworks/__init__.py +5 -0
- agno/models/fireworks/fireworks.py +26 -0
- agno/models/google/__init__.py +5 -0
- agno/models/google/gemini.py +1085 -0
- agno/models/groq/__init__.py +5 -0
- agno/models/groq/groq.py +556 -0
- agno/models/huggingface/__init__.py +5 -0
- agno/models/huggingface/huggingface.py +491 -0
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +422 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +26 -0
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +48 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +468 -0
- agno/models/litellm/litellm_openai.py +25 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +434 -0
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +475 -0
- agno/models/meta/llama_openai.py +78 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +5 -0
- agno/models/mistral/mistral.py +432 -0
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +54 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +5 -0
- agno/models/nvidia/nvidia.py +28 -0
- agno/models/ollama/__init__.py +5 -0
- agno/models/ollama/chat.py +441 -0
- agno/models/openai/__init__.py +9 -0
- agno/models/openai/chat.py +883 -0
- agno/models/openai/like.py +27 -0
- agno/models/openai/responses.py +1050 -0
- agno/models/openrouter/__init__.py +5 -0
- agno/models/openrouter/openrouter.py +66 -0
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +187 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +81 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +199 -0
- agno/models/sambanova/__init__.py +5 -0
- agno/models/sambanova/sambanova.py +28 -0
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/__init__.py +5 -0
- agno/models/together/together.py +25 -0
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +26 -0
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +70 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +78 -0
- agno/models/xai/__init__.py +3 -0
- agno/models/xai/xai.py +113 -0
- agno/os/__init__.py +3 -0
- agno/os/app.py +876 -0
- agno/os/auth.py +57 -0
- agno/os/config.py +104 -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/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +144 -0
- agno/os/interfaces/agui/utils.py +534 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +211 -0
- agno/os/interfaces/whatsapp/security.py +53 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +292 -0
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +1763 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +430 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +162 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +997 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +515 -0
- agno/os/routers/memory/schemas.py +62 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/schema.py +1055 -0
- agno/os/settings.py +43 -0
- agno/os/utils.py +630 -0
- agno/py.typed +0 -0
- agno/reasoning/__init__.py +0 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +63 -0
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +31 -0
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +787 -0
- agno/run/base.py +229 -0
- agno/run/cancel.py +81 -0
- agno/run/messages.py +32 -0
- agno/run/team.py +753 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +295 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +392 -0
- agno/session/workflow.py +205 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +8793 -0
- agno/tools/__init__.py +10 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +69 -0
- agno/tools/api.py +122 -0
- agno/tools/apify.py +314 -0
- agno/tools/arxiv.py +127 -0
- agno/tools/aws_lambda.py +53 -0
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +89 -0
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +255 -0
- agno/tools/calculator.py +151 -0
- agno/tools/cartesia.py +187 -0
- agno/tools/clickup.py +244 -0
- agno/tools/confluence.py +240 -0
- agno/tools/crawl4ai.py +158 -0
- agno/tools/csv_toolkit.py +185 -0
- agno/tools/dalle.py +110 -0
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +262 -0
- agno/tools/desi_vocal.py +108 -0
- agno/tools/discord.py +161 -0
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +379 -0
- agno/tools/duckduckgo.py +91 -0
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +196 -0
- agno/tools/email.py +67 -0
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +396 -0
- agno/tools/fal.py +127 -0
- agno/tools/file.py +240 -0
- agno/tools/file_generation.py +350 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +143 -0
- agno/tools/function.py +1187 -0
- agno/tools/giphy.py +93 -0
- agno/tools/github.py +1760 -0
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +270 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +674 -0
- agno/tools/googlesearch.py +98 -0
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +77 -0
- agno/tools/jina.py +101 -0
- agno/tools/jira.py +170 -0
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +426 -0
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +90 -0
- agno/tools/lumalab.py +183 -0
- 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 +193 -0
- agno/tools/memori.py +339 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +139 -0
- agno/tools/models/__init__.py +0 -0
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +195 -0
- agno/tools/moviepy_video.py +349 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +46 -0
- agno/tools/newspaper4k.py +93 -0
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +202 -0
- agno/tools/openbb.py +160 -0
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +102 -0
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +257 -0
- agno/tools/pubmed.py +188 -0
- agno/tools/python.py +205 -0
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +467 -0
- agno/tools/replicate.py +117 -0
- agno/tools/resend.py +62 -0
- agno/tools/scrapegraph.py +222 -0
- agno/tools/searxng.py +152 -0
- agno/tools/serpapi.py +116 -0
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +53 -0
- agno/tools/slack.py +136 -0
- agno/tools/sleep.py +20 -0
- agno/tools/spider.py +116 -0
- agno/tools/sql.py +154 -0
- agno/tools/streamlit/__init__.py +0 -0
- agno/tools/streamlit/components.py +113 -0
- agno/tools/tavily.py +254 -0
- agno/tools/telegram.py +48 -0
- agno/tools/todoist.py +218 -0
- agno/tools/tool_registry.py +1 -0
- agno/tools/toolkit.py +146 -0
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +274 -0
- agno/tools/twilio.py +186 -0
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +54 -0
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +63 -0
- agno/tools/workflow.py +278 -0
- agno/tools/x.py +335 -0
- agno/tools/yfinance.py +257 -0
- agno/tools/youtube.py +184 -0
- agno/tools/zendesk.py +82 -0
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +382 -0
- agno/utils/__init__.py +0 -0
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +49 -0
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +132 -0
- agno/utils/dttm.py +13 -0
- agno/utils/enum.py +22 -0
- agno/utils/env.py +11 -0
- agno/utils/events.py +696 -0
- agno/utils/format_str.py +16 -0
- agno/utils/functions.py +166 -0
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +74 -0
- agno/utils/json_schema.py +234 -0
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +255 -0
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +352 -0
- agno/utils/merge_dict.py +41 -0
- agno/utils/message.py +118 -0
- agno/utils/models/__init__.py +0 -0
- agno/utils/models/ai_foundry.py +43 -0
- agno/utils/models/claude.py +358 -0
- agno/utils/models/cohere.py +87 -0
- agno/utils/models/llama.py +78 -0
- agno/utils/models/mistral.py +98 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +32 -0
- agno/utils/pprint.py +178 -0
- agno/utils/print_response/__init__.py +0 -0
- agno/utils/print_response/agent.py +842 -0
- agno/utils/print_response/team.py +1724 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/response_iterator.py +17 -0
- agno/utils/safe_formatter.py +24 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +22 -0
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +231 -0
- agno/utils/team.py +139 -0
- agno/utils/timer.py +41 -0
- agno/utils/tools.py +102 -0
- agno/utils/web.py +23 -0
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +25 -0
- agno/vectordb/__init__.py +3 -0
- agno/vectordb/base.py +127 -0
- agno/vectordb/cassandra/__init__.py +5 -0
- agno/vectordb/cassandra/cassandra.py +501 -0
- agno/vectordb/cassandra/extra_param_mixin.py +11 -0
- agno/vectordb/cassandra/index.py +13 -0
- agno/vectordb/chroma/__init__.py +5 -0
- agno/vectordb/chroma/chromadb.py +929 -0
- agno/vectordb/clickhouse/__init__.py +9 -0
- agno/vectordb/clickhouse/clickhousedb.py +835 -0
- agno/vectordb/clickhouse/index.py +9 -0
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1442 -0
- agno/vectordb/distance.py +7 -0
- agno/vectordb/lancedb/__init__.py +6 -0
- agno/vectordb/lancedb/lance_db.py +995 -0
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +4 -0
- agno/vectordb/milvus/milvus.py +1182 -0
- agno/vectordb/mongodb/__init__.py +9 -0
- agno/vectordb/mongodb/mongodb.py +1417 -0
- agno/vectordb/pgvector/__init__.py +12 -0
- agno/vectordb/pgvector/index.py +23 -0
- agno/vectordb/pgvector/pgvector.py +1462 -0
- agno/vectordb/pineconedb/__init__.py +5 -0
- agno/vectordb/pineconedb/pineconedb.py +747 -0
- agno/vectordb/qdrant/__init__.py +5 -0
- agno/vectordb/qdrant/qdrant.py +1134 -0
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/search.py +7 -0
- agno/vectordb/singlestore/__init__.py +10 -0
- agno/vectordb/singlestore/index.py +41 -0
- agno/vectordb/singlestore/singlestore.py +763 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +699 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1005 -0
- agno/workflow/__init__.py +23 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +738 -0
- agno/workflow/loop.py +735 -0
- agno/workflow/parallel.py +824 -0
- agno/workflow/router.py +702 -0
- agno/workflow/step.py +1432 -0
- agno/workflow/steps.py +592 -0
- agno/workflow/types.py +520 -0
- agno/workflow/workflow.py +4321 -0
- agno-2.2.13.dist-info/METADATA +614 -0
- agno-2.2.13.dist-info/RECORD +575 -0
- agno-2.2.13.dist-info/WHEEL +5 -0
- agno-2.2.13.dist-info/licenses/LICENSE +201 -0
- agno-2.2.13.dist-info/top_level.txt +1 -0
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
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Any, List, Literal, Optional, Union
|
|
3
|
+
from uuid import uuid4
|
|
4
|
+
|
|
5
|
+
from agno.agent import Agent
|
|
6
|
+
from agno.media import Audio, Image
|
|
7
|
+
from agno.team.team import Team
|
|
8
|
+
from agno.tools import Toolkit
|
|
9
|
+
from agno.tools.function import ToolResult
|
|
10
|
+
from agno.utils.log import log_debug, log_error, log_warning
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from openai import OpenAI as OpenAIClient
|
|
14
|
+
except (ModuleNotFoundError, ImportError):
|
|
15
|
+
raise ImportError("`openai` not installed. Please install using `pip install openai`")
|
|
16
|
+
|
|
17
|
+
# Define only types specifically needed by OpenAITools class
|
|
18
|
+
OpenAIVoice = Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
|
|
19
|
+
OpenAITTSModel = Literal["tts-1", "tts-1-hd"]
|
|
20
|
+
OpenAITTSFormat = Literal["mp3", "opus", "aac", "flac", "wav", "pcm"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class OpenAITools(Toolkit):
|
|
24
|
+
"""Tools for interacting with OpenAI API.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
api_key (str, optional): OpenAI API key. Retrieved from OPENAI_API_KEY env variable if not provided.
|
|
28
|
+
enable_transcription (bool): Enable audio transcription functionality. Default is True.
|
|
29
|
+
enable_image_generation (bool): Enable image generation functionality. Default is True.
|
|
30
|
+
enable_speech_generation (bool): Enable speech generation functionality. Default is True.
|
|
31
|
+
all (bool): Enable all tools. Overrides individual flags when True. Default is False.
|
|
32
|
+
transcription_model (str): Model to use for transcription. Default is "whisper-1".
|
|
33
|
+
text_to_speech_voice (OpenAIVoice): Voice to use for TTS. Default is "alloy".
|
|
34
|
+
text_to_speech_model (OpenAITTSModel): Model to use for TTS. Default is "tts-1".
|
|
35
|
+
text_to_speech_format (OpenAITTSFormat): Audio format for TTS. Default is "mp3".
|
|
36
|
+
image_model (str, optional): Model to use for image generation. Default is "dall-e-3".
|
|
37
|
+
image_quality (str, optional): Quality setting for image generation.
|
|
38
|
+
image_size (str, optional): Size setting for image generation.
|
|
39
|
+
image_style (str, optional): Style setting for image generation.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
api_key: Optional[str] = None,
|
|
45
|
+
enable_transcription: bool = True,
|
|
46
|
+
enable_image_generation: bool = True,
|
|
47
|
+
enable_speech_generation: bool = True,
|
|
48
|
+
all: bool = False,
|
|
49
|
+
transcription_model: str = "whisper-1",
|
|
50
|
+
text_to_speech_voice: OpenAIVoice = "alloy",
|
|
51
|
+
text_to_speech_model: OpenAITTSModel = "tts-1",
|
|
52
|
+
text_to_speech_format: OpenAITTSFormat = "mp3",
|
|
53
|
+
image_model: Optional[str] = "dall-e-3",
|
|
54
|
+
image_quality: Optional[str] = None,
|
|
55
|
+
image_size: Optional[Literal["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"]] = None,
|
|
56
|
+
image_style: Optional[Literal["vivid", "natural"]] = None,
|
|
57
|
+
**kwargs,
|
|
58
|
+
):
|
|
59
|
+
self.api_key = api_key or getenv("OPENAI_API_KEY")
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
raise ValueError("OPENAI_API_KEY not set. Please set the OPENAI_API_KEY environment variable.")
|
|
62
|
+
|
|
63
|
+
self.transcription_model = transcription_model
|
|
64
|
+
# Store TTS defaults
|
|
65
|
+
self.tts_voice = text_to_speech_voice
|
|
66
|
+
self.tts_model = text_to_speech_model
|
|
67
|
+
self.tts_format = text_to_speech_format
|
|
68
|
+
self.image_model = image_model
|
|
69
|
+
self.image_quality = image_quality
|
|
70
|
+
self.image_style = image_style
|
|
71
|
+
self.image_size = image_size
|
|
72
|
+
|
|
73
|
+
tools: List[Any] = []
|
|
74
|
+
if all or enable_transcription:
|
|
75
|
+
tools.append(self.transcribe_audio)
|
|
76
|
+
if all or enable_image_generation:
|
|
77
|
+
tools.append(self.generate_image)
|
|
78
|
+
if all or enable_speech_generation:
|
|
79
|
+
tools.append(self.generate_speech)
|
|
80
|
+
|
|
81
|
+
super().__init__(name="openai_tools", tools=tools, **kwargs)
|
|
82
|
+
|
|
83
|
+
def transcribe_audio(self, audio_path: str) -> str:
|
|
84
|
+
"""Transcribe audio file using OpenAI's Whisper API
|
|
85
|
+
Args:
|
|
86
|
+
audio_path: Path to the audio file
|
|
87
|
+
"""
|
|
88
|
+
log_debug(f"Transcribing audio from {audio_path}")
|
|
89
|
+
try:
|
|
90
|
+
audio_file = open(audio_path, "rb")
|
|
91
|
+
|
|
92
|
+
transcript = OpenAIClient(api_key=self.api_key).audio.transcriptions.create(
|
|
93
|
+
model=self.transcription_model,
|
|
94
|
+
file=audio_file,
|
|
95
|
+
response_format="text",
|
|
96
|
+
)
|
|
97
|
+
except Exception as e: # type: ignore[return]
|
|
98
|
+
log_error(f"Failed to transcribe audio: {str(e)}")
|
|
99
|
+
return f"Failed to transcribe audio: {str(e)}"
|
|
100
|
+
|
|
101
|
+
log_debug(f"Transcript: {transcript}")
|
|
102
|
+
return transcript # type: ignore[return-value]
|
|
103
|
+
|
|
104
|
+
def generate_image(
|
|
105
|
+
self,
|
|
106
|
+
prompt: str,
|
|
107
|
+
) -> ToolResult:
|
|
108
|
+
"""Generate images based on a text prompt.
|
|
109
|
+
Args:
|
|
110
|
+
prompt (str): The text prompt to generate the image from.
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
import base64
|
|
114
|
+
|
|
115
|
+
extra_params = {
|
|
116
|
+
"size": self.image_size,
|
|
117
|
+
"quality": self.image_quality,
|
|
118
|
+
"style": self.image_style,
|
|
119
|
+
}
|
|
120
|
+
extra_params = {k: v for k, v in extra_params.items() if v is not None}
|
|
121
|
+
|
|
122
|
+
# gpt-image-1 by default outputs a base64 encoded image but other models do not
|
|
123
|
+
# so we add a response_format parameter to have consistent output.
|
|
124
|
+
if self.image_model and self.image_model.startswith("gpt-image"):
|
|
125
|
+
response = OpenAIClient(api_key=self.api_key).images.generate(
|
|
126
|
+
model=self.image_model,
|
|
127
|
+
prompt=prompt,
|
|
128
|
+
**extra_params, # type: ignore
|
|
129
|
+
)
|
|
130
|
+
else:
|
|
131
|
+
response = OpenAIClient(api_key=self.api_key).images.generate(
|
|
132
|
+
model=self.image_model,
|
|
133
|
+
prompt=prompt,
|
|
134
|
+
response_format="b64_json",
|
|
135
|
+
**extra_params, # type: ignore
|
|
136
|
+
)
|
|
137
|
+
data = None
|
|
138
|
+
if hasattr(response, "data") and response.data:
|
|
139
|
+
data = response.data[0]
|
|
140
|
+
if data is None:
|
|
141
|
+
log_warning("OpenAI API did not return any data.")
|
|
142
|
+
return ToolResult(content="Failed to generate image: No data received from API.")
|
|
143
|
+
|
|
144
|
+
if hasattr(data, "b64_json") and data.b64_json:
|
|
145
|
+
image_base64 = data.b64_json
|
|
146
|
+
media_id = str(uuid4())
|
|
147
|
+
|
|
148
|
+
# Decode base64 to bytes for proper storage
|
|
149
|
+
image_bytes = base64.b64decode(image_base64)
|
|
150
|
+
|
|
151
|
+
# Create ImageArtifact and return in ToolResult
|
|
152
|
+
image_artifact = Image(
|
|
153
|
+
id=media_id,
|
|
154
|
+
content=image_bytes, # ← Store as bytes, not encoded string
|
|
155
|
+
mime_type="image/png",
|
|
156
|
+
original_prompt=prompt,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return ToolResult(
|
|
160
|
+
content="Image generated successfully.",
|
|
161
|
+
images=[image_artifact],
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return ToolResult(content="Failed to generate image: No content received from API.")
|
|
165
|
+
except Exception as e:
|
|
166
|
+
log_error(f"Failed to generate image using {self.image_model}: {e}")
|
|
167
|
+
return ToolResult(content=f"Failed to generate image: {e}")
|
|
168
|
+
|
|
169
|
+
def generate_speech(
|
|
170
|
+
self,
|
|
171
|
+
agent: Union[Agent, Team],
|
|
172
|
+
text_input: str,
|
|
173
|
+
) -> ToolResult: # Changed return type
|
|
174
|
+
"""Generate speech from text using OpenAI's Text-to-Speech API.
|
|
175
|
+
Args:
|
|
176
|
+
text_input (str): The text to synthesize into speech.
|
|
177
|
+
"""
|
|
178
|
+
try:
|
|
179
|
+
response = OpenAIClient(api_key=self.api_key).audio.speech.create(
|
|
180
|
+
model=self.tts_model,
|
|
181
|
+
voice=self.tts_voice,
|
|
182
|
+
input=text_input,
|
|
183
|
+
response_format=self.tts_format,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Get raw audio data for artifact creation before potentially saving
|
|
187
|
+
audio_data: bytes = response.content
|
|
188
|
+
|
|
189
|
+
# Create AudioArtifact and return in ToolResult
|
|
190
|
+
media_id = str(uuid4())
|
|
191
|
+
audio_artifact = Audio(
|
|
192
|
+
id=media_id,
|
|
193
|
+
content=audio_data,
|
|
194
|
+
mime_type=f"audio/{self.tts_format}",
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return ToolResult(
|
|
198
|
+
content=f"Speech generated successfully with ID: {media_id}",
|
|
199
|
+
audios=[audio_artifact],
|
|
200
|
+
)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
return ToolResult(content=f"Failed to generate speech: {str(e)}")
|
agno/tools/openbb.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, List, Literal, Optional
|
|
4
|
+
|
|
5
|
+
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import log_debug, logger
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from openbb import obb as openbb_app
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError("`openbb` not installed. Please install using `pip install 'openbb'`.")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class OpenBBTools(Toolkit):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
obb: Optional[Any] = None,
|
|
18
|
+
openbb_pat: Optional[str] = None,
|
|
19
|
+
provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = "yfinance",
|
|
20
|
+
enable_get_stock_price: bool = True,
|
|
21
|
+
enable_search_company_symbol: bool = False,
|
|
22
|
+
enable_get_company_news: bool = False,
|
|
23
|
+
enable_get_company_profile: bool = False,
|
|
24
|
+
enable_get_price_targets: bool = False,
|
|
25
|
+
all: bool = False,
|
|
26
|
+
**kwargs,
|
|
27
|
+
):
|
|
28
|
+
self.obb = obb or openbb_app
|
|
29
|
+
try:
|
|
30
|
+
if openbb_pat or getenv("OPENBB_PAT"):
|
|
31
|
+
self.obb.account.login(pat=openbb_pat or getenv("OPENBB_PAT")) # type: ignore
|
|
32
|
+
except Exception as e:
|
|
33
|
+
logger.error(f"Error logging into OpenBB: {e}")
|
|
34
|
+
|
|
35
|
+
self.provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = provider
|
|
36
|
+
|
|
37
|
+
tools: List[Any] = []
|
|
38
|
+
if enable_get_stock_price or all:
|
|
39
|
+
tools.append(self.get_stock_price)
|
|
40
|
+
if enable_search_company_symbol or all:
|
|
41
|
+
tools.append(self.search_company_symbol)
|
|
42
|
+
if enable_get_company_news or all:
|
|
43
|
+
tools.append(self.get_company_news)
|
|
44
|
+
if enable_get_company_profile or all:
|
|
45
|
+
tools.append(self.get_company_profile)
|
|
46
|
+
if enable_get_price_targets or all:
|
|
47
|
+
tools.append(self.get_price_targets)
|
|
48
|
+
|
|
49
|
+
super().__init__(name="openbb_tools", tools=tools, **kwargs)
|
|
50
|
+
|
|
51
|
+
def get_stock_price(self, symbol: str) -> str:
|
|
52
|
+
"""Use this function to get the current stock price for a stock symbol or list of symbols.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
symbol (str): The stock symbol or list of stock symbols.
|
|
56
|
+
Eg: "AAPL" or "AAPL,MSFT,GOOGL"
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
str: The current stock prices or error message.
|
|
60
|
+
"""
|
|
61
|
+
try:
|
|
62
|
+
log_debug(f"Fetching current price for {symbol}")
|
|
63
|
+
result = self.obb.equity.price.quote(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
64
|
+
clean_results = []
|
|
65
|
+
for row in result.to_dicts():
|
|
66
|
+
clean_results.append(
|
|
67
|
+
{
|
|
68
|
+
"symbol": row.get("symbol"),
|
|
69
|
+
"last_price": row.get("last_price"),
|
|
70
|
+
"currency": row.get("currency"),
|
|
71
|
+
"name": row.get("name"),
|
|
72
|
+
"high": row.get("high"),
|
|
73
|
+
"low": row.get("low"),
|
|
74
|
+
"open": row.get("open"),
|
|
75
|
+
"close": row.get("close"),
|
|
76
|
+
"prev_close": row.get("prev_close"),
|
|
77
|
+
"volume": row.get("volume"),
|
|
78
|
+
"ma_50d": row.get("ma_50d"),
|
|
79
|
+
"ma_200d": row.get("ma_200d"),
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
return json.dumps(clean_results, indent=2, default=str)
|
|
83
|
+
except Exception as e:
|
|
84
|
+
return f"Error fetching current price for {symbol}: {e}"
|
|
85
|
+
|
|
86
|
+
def search_company_symbol(self, company_name: str) -> str:
|
|
87
|
+
"""Use this function to get a list of ticker symbols for a company.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
company_name (str): The name of the company.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
str: A JSON string containing the ticker symbols.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
log_debug(f"Search ticker for {company_name}")
|
|
97
|
+
result = self.obb.equity.search(company_name).to_polars() # type: ignore
|
|
98
|
+
clean_results = []
|
|
99
|
+
if len(result) > 0:
|
|
100
|
+
for row in result.to_dicts():
|
|
101
|
+
clean_results.append({"symbol": row.get("symbol"), "name": row.get("name")})
|
|
102
|
+
|
|
103
|
+
return json.dumps(clean_results, indent=2, default=str)
|
|
104
|
+
|
|
105
|
+
def get_price_targets(self, symbol: str) -> str:
|
|
106
|
+
"""Use this function to get consensus price target and recommendations for a stock symbol or list of symbols.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
symbol (str): The stock symbol or list of stock symbols.
|
|
110
|
+
Eg: "AAPL" or "AAPL,MSFT,GOOGL"
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
str: JSON containing consensus price target and recommendations.
|
|
114
|
+
"""
|
|
115
|
+
try:
|
|
116
|
+
log_debug(f"Fetching price targets for {symbol}")
|
|
117
|
+
result = self.obb.equity.estimates.consensus(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
118
|
+
return json.dumps(result.to_dicts(), indent=2, default=str)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
return f"Error fetching company news for {symbol}: {e}"
|
|
121
|
+
|
|
122
|
+
def get_company_news(self, symbol: str, num_stories: int = 10) -> str:
|
|
123
|
+
"""Use this function to get company news for a stock symbol or list of symbols.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
symbol (str): The stock symbol or list of stock symbols.
|
|
127
|
+
Eg: "AAPL" or "AAPL,MSFT,GOOGL"
|
|
128
|
+
num_stories (int): The number of news stories to return. Defaults to 10.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
str: JSON containing company news and press releases.
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
log_debug(f"Fetching news for {symbol}")
|
|
135
|
+
result = self.obb.news.company(symbol=symbol, provider=self.provider, limit=num_stories).to_polars() # type: ignore
|
|
136
|
+
clean_results = []
|
|
137
|
+
if len(result) > 0:
|
|
138
|
+
for row in result.to_dicts():
|
|
139
|
+
row.pop("images")
|
|
140
|
+
clean_results.append(row)
|
|
141
|
+
return json.dumps(clean_results[:num_stories], indent=2, default=str)
|
|
142
|
+
except Exception as e:
|
|
143
|
+
return f"Error fetching company news for {symbol}: {e}"
|
|
144
|
+
|
|
145
|
+
def get_company_profile(self, symbol: str) -> str:
|
|
146
|
+
"""Use this function to get company profile and overview for a stock symbol or list of symbols.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
symbol (str): The stock symbol or list of stock symbols.
|
|
150
|
+
Eg: "AAPL" or "AAPL,MSFT,GOOGL"
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: JSON containing company profile and overview.
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
log_debug(f"Fetching company profile for {symbol}")
|
|
157
|
+
result = self.obb.equity.profile(symbol=symbol, provider=self.provider).to_polars() # type: ignore
|
|
158
|
+
return json.dumps(result.to_dicts(), indent=2, default=str)
|
|
159
|
+
except Exception as e:
|
|
160
|
+
return f"Error fetching company profile for {symbol}: {e}"
|