From cf9100010f34fa190fbaaebd21d8bb6a0b5a4aba Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 1 Sep 2026 17:44:43 +0530 Subject: [PATCH 1/3] fix: correct retired model ids and stale API references for v3.0 Groq: retired llama-3.3-70b-versatile / llama-3.1-8b-instant replaced with openai/gpt-oss-120b / openai/gpt-oss-20b across 11 hand-written pages, with Groq's dated shutdown in a Warning and the Preview-only vision situation stated; image agent moved to qwen/qwen3.6-27b. Gemini default rows to gemini-3.7-flash. Cerebras overviews: dated scout deprecation, gpt-oss-120b default rows, retired-model note on parallel_tool_calls. OpenAI: the four widened request-param types on five param tables. Anthropic: anthropic>=0.77.0 floor with the output_config explanation; two stale output_format notes. Sheets/BigQuery: legacy enable_* aliases documented as accepted. Toolkit reference: id row (reserved) and the positional-tools Warning. MultiMCPTools removed from 11 hand-written pages; multiple-servers rewritten around one MCPTools per server with the real connection-failure semantics. Smaller: DuckDuckGo alias removal, Seltz max_documents (legacy SDK path retained, pin stays >=0.2.0), BrightData output_path, Brandfetch async_tools, RedisDB -> RedisDb with the RedisVectorDb disambiguation, Mistral mistralai>=2.0.0, metrics reference alias claim, @tool title/annotations rows, one stray retired Groq id. Docs changelog and migration guide gain the entries that shipped without them; the Toolkit id entries drop the unsupported 'used by AgentOS' claim. --- examples/tools/brandfetch-tools.mdx | 2 +- examples/tools/mcp/overview.mdx | 6 +- examples/tools/mcp/sse-transport/overview.mdx | 4 +- .../streamable-http-transport/overview.mdx | 4 +- faq/import-errors.mdx | 2 +- knowledge/vector-stores/redis/overview.mdx | 10 +- .../redis/usage/async-redis-db.mdx | 4 +- .../vector-stores/redis/usage/redis-db.mdx | 4 +- .../gateways/cerebras-openai/overview.mdx | 6 +- .../providers/gateways/cerebras/overview.mdx | 6 +- models/providers/gateways/groq/overview.mdx | 18 ++- .../gateways/groq/usage/basic-stream.mdx | 2 +- .../providers/gateways/groq/usage/basic.mdx | 2 +- .../gateways/groq/usage/deep-knowledge.mdx | 2 +- .../gateways/groq/usage/image-agent.mdx | 8 +- .../gateways/groq/usage/knowledge.mdx | 2 +- .../providers/gateways/groq/usage/metrics.mdx | 2 +- .../gateways/groq/usage/reasoning-agent.mdx | 4 +- .../gateways/groq/usage/structured-output.mdx | 2 +- .../gateways/groq/usage/tool-use.mdx | 2 +- .../providers/native/anthropic/overview.mdx | 10 +- .../anthropic/usage/structured-output.mdx | 2 +- .../native/google/gemini-interactions.mdx | 2 +- models/providers/native/google/overview.mdx | 2 +- models/providers/native/mistral/overview.mdx | 4 +- .../native/openai/completion/overview.mdx | 6 +- .../native/openai/responses/overview.mdx | 8 +- other/v3-changelog.mdx | 20 ++- other/v3-migration.mdx | 28 +++- .../usage/tools/groq-reasoning-tools.mdx | 2 +- reference/models/gemini.mdx | 2 +- reference/models/groq.mdx | 2 +- reference/models/open-responses.mdx | 8 +- reference/models/openai-like.mdx | 6 +- reference/models/openai.mdx | 6 +- reference/run/metrics.mdx | 7 +- reference/tools/decorator.mdx | 2 + reference/tools/toolkit.mdx | 5 + tools/mcp/dynamic-headers.mdx | 24 ++-- tools/mcp/multiple-servers.mdx | 129 ++---------------- tools/mcp/overview.mdx | 6 +- tools/mcp/server-params.mdx | 2 +- tools/mcp/transports/sse.mdx | 30 ++-- tools/mcp/transports/stdio.mdx | 29 ++-- tools/mcp/transports/streamable_http.mdx | 31 ++--- tools/toolkits/database/google-bigquery.mdx | 4 + tools/toolkits/others/google-sheets.mdx | 4 + tools/toolkits/search/duckduckgo.mdx | 6 +- tools/toolkits/search/seltz.mdx | 5 +- tools/toolkits/web-scrape/brightdata.mdx | 2 +- 50 files changed, 221 insertions(+), 265 deletions(-) diff --git a/examples/tools/brandfetch-tools.mdx b/examples/tools/brandfetch-tools.mdx index 1650ee9d5..46ee5a490 100644 --- a/examples/tools/brandfetch-tools.mdx +++ b/examples/tools/brandfetch-tools.mdx @@ -44,7 +44,7 @@ from agno.tools.brandfetch import BrandfetchTools # Brand Search API agent = Agent( - tools=[BrandfetchTools(async_tools=True)], + tools=[BrandfetchTools()], description="You are a Brand research agent. Given a company name or company domain, you will use the Brandfetch API to retrieve the company's brand information.", ) diff --git a/examples/tools/mcp/overview.mdx b/examples/tools/mcp/overview.mdx index 99d80d72d..bdbd18207 100644 --- a/examples/tools/mcp/overview.mdx +++ b/examples/tools/mcp/overview.mdx @@ -8,7 +8,7 @@ description: "Enable Agno agents to interact with external systems via MCP inter | [MCP GitHub Agent](/examples/tools/mcp/github) | Create a GitHub agent that uses MCP to explore, analyze, and provide insights about GitHub repositories. | | [Groq + MCP = Lightning Fast Agents](/examples/tools/mcp/groq-mcp) | Create a high-performance filesystem agent by combining Groq's fast LLM inference with the Model Context Protocol (MCP). | | [Include Exclude Tools](/examples/tools/mcp/include-exclude-tools) | Filter which MCP server tools an agent can use with include_tools and exclude_tools. | -| [Multiple Servers](/examples/tools/mcp/multiple-servers) | Connect one agent to Airbnb and Brave Search MCP servers at once using MultiMCPTools. | +| [Multiple Servers](/examples/tools/mcp/multiple-servers) | Connect one agent to Airbnb and Brave Search MCP servers at once using one MCPTools instance per server. | | [Sequential Thinking](/examples/tools/mcp/sequential-thinking) | Pair the Sequential Thinking MCP server with YFinanceTools so an agent reasons step by step before comparing two stocks. | | [MCP Airbnb Agent](/examples/tools/mcp/airbnb) | Create an agent that uses MCP and Gemini 2.5 Pro to search for Airbnb listings. | | [Agno MCP](/examples/tools/mcp/agno-mcp) | Query the Agno docs MCP server over streamable HTTP with MCPTools and a Claude agent. | @@ -35,6 +35,6 @@ description: "Enable Agno agents to interact with external systems via MCP inter | [Dynamic Headers](/examples/tools/mcp/dynamic-headers/overview) | Dynamically send information to the MCP server via HTTP headers. | | [Local Server](/examples/tools/mcp/local-server/overview) | Run a local FastMCP weather server over stdio and connect an Agno agent to it with MCPTools. | | [Mcp Toolbox Demo](/examples/tools/mcp/mcp-toolbox-demo/overview) | Run Agno agents and workflows against a PostgreSQL database through the MCP Toolbox for Databases server. | -| [Sse Transport](/examples/tools/mcp/sse-transport/overview) | Connect agents to an MCP server over SSE transport using MCPTools and MultiMCPTools. | -| [Streamable Http Transport](/examples/tools/mcp/streamable-http-transport/overview) | Connect an Agno agent to a Streamable HTTP MCP server using MCPTools and MultiMCPTools. | +| [Sse Transport](/examples/tools/mcp/sse-transport/overview) | Connect agents to an MCP server over SSE transport using MCPTools. | +| [Streamable Http Transport](/examples/tools/mcp/streamable-http-transport/overview) | Connect an Agno agent to a Streamable HTTP MCP server using MCPTools. | | [MCP BGPT Agent - Evidence-grounded scientific paper search](/examples/tools/mcp/bgpt) | Query the hosted BGPT MCP server over Streamable HTTP to search papers and surface methods, sample sizes, limitations, and conflicts of interest. | diff --git a/examples/tools/mcp/sse-transport/overview.mdx b/examples/tools/mcp/sse-transport/overview.mdx index 3410a6b0c..bc93ecbf8 100644 --- a/examples/tools/mcp/sse-transport/overview.mdx +++ b/examples/tools/mcp/sse-transport/overview.mdx @@ -1,8 +1,8 @@ --- title: "Overview" -description: "Connect agents to an MCP server over SSE transport using MCPTools and MultiMCPTools." +description: "Connect agents to an MCP server over SSE transport using MCPTools." --- | Example | Description | |---------|-------------| -| [Client](/examples/tools/mcp/sse-transport/client) | Connect an OpenAI agent to an SSE MCP server with MCPTools, and to SSE plus stdio servers together with MultiMCPTools. | +| [Client](/examples/tools/mcp/sse-transport/client) | Connect an OpenAI agent to an SSE MCP server with MCPTools, and to SSE plus stdio servers together with one MCPTools instance per server. | | [Server](/examples/tools/mcp/sse-transport/server) | Start an example MCP server that uses the SSE transport. | diff --git a/examples/tools/mcp/streamable-http-transport/overview.mdx b/examples/tools/mcp/streamable-http-transport/overview.mdx index ac774f5c4..c87b555ea 100644 --- a/examples/tools/mcp/streamable-http-transport/overview.mdx +++ b/examples/tools/mcp/streamable-http-transport/overview.mdx @@ -1,8 +1,8 @@ --- title: "Overview" -description: "Connect an Agno agent to a Streamable HTTP MCP server using MCPTools and MultiMCPTools." +description: "Connect an Agno agent to a Streamable HTTP MCP server using MCPTools." --- | Example | Description | |---------|-------------| -| [Client](/examples/tools/mcp/streamable-http-transport/client) | Show how to connect to MCP servers that use either SSE or Streamable HTTP transport using our MCPTools and MultiMCPTools classes. | +| [Client](/examples/tools/mcp/streamable-http-transport/client) | Show how to connect to MCP servers that use either SSE or Streamable HTTP transport using our MCPTools class. | | [Server](/examples/tools/mcp/streamable-http-transport/server) | Start an example MCP server that uses the Streamable HTTP transport. | diff --git a/faq/import-errors.mdx b/faq/import-errors.mdx index 5f0e8aa77..60bf5f2ef 100644 --- a/faq/import-errors.mdx +++ b/faq/import-errors.mdx @@ -20,7 +20,7 @@ pip install -U 'agno[os,psycopg,sql,pgvector]' | `google-genai` not installed or not at the latest version | `Gemini`, `GeminiEmbedder` | `pip install 'agno[google]'` | | `groq` not installed | `Groq` | `pip install 'agno[groq]'` | | No module named `fastapi` / `PyJWT` is not installed | `AgentOS` | `pip install 'agno[os]'` | -| `mcp` not installed | `MCPTools`, `MultiMCPTools` | `pip install 'agno[mcp]'` | +| `mcp` not installed | `MCPTools` | `pip install 'agno[mcp]'` | | `fastmcp` not installed | `AgentOS(mcp_server=True)` | `pip install 'agno[mcp]'` | | `sqlalchemy` not installed | `SqliteDb` | `pip install 'agno[sqlite]'` | | `sqlalchemy` not installed | `PostgresDb` | `pip install 'agno[sql,psycopg]'` | diff --git a/knowledge/vector-stores/redis/overview.mdx b/knowledge/vector-stores/redis/overview.mdx index f42e783fc..6fb1ab9d1 100644 --- a/knowledge/vector-stores/redis/overview.mdx +++ b/knowledge/vector-stores/redis/overview.mdx @@ -16,7 +16,11 @@ You can use Redis as a vector database with Agno. uv pip install -U redis redisvl pypdf openai agno ``` -For connecting to a remote Redis instance, pass your Redis connection string to the `redis_url` parameter and the index name to the `index_name` parameter of the `RedisDB` constructor. +For connecting to a remote Redis instance, pass your Redis connection string to the `redis_url` parameter and the index name to the `index_name` parameter of the `RedisDb` constructor. + + +The vector store class was renamed from `RedisDB` to `RedisDb` in Agno v3.0; the old spelling still works as a deprecated alias. Because the session storage adapter in `agno.db.redis` is also named `RedisDb`, the vector store is additionally exported as `RedisVectorDb` — use that spelling when both are imported in the same module. + For a local docker setup, you can use the following command: @@ -34,7 +38,7 @@ import os from agno.agent import Agent from agno.knowledge.knowledge import Knowledge -from agno.vectordb.redis import RedisDB +from agno.vectordb.redis import RedisDb from agno.vectordb.search import SearchType # Configure Redis connection (from environment variables if available, otherwise use local defaults) @@ -42,7 +46,7 @@ REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") INDEX_NAME = os.getenv("REDIS_INDEX", "agno_cookbook_vectors") # Initialize Redis Vector DB -vector_db = RedisDB( +vector_db = RedisDb( index_name=INDEX_NAME, redis_url=REDIS_URL, search_type=SearchType.vector, # try SearchType.hybrid for hybrid search diff --git a/knowledge/vector-stores/redis/usage/async-redis-db.mdx b/knowledge/vector-stores/redis/usage/async-redis-db.mdx index b6d0ba89c..b18849d8e 100644 --- a/knowledge/vector-stores/redis/usage/async-redis-db.mdx +++ b/knowledge/vector-stores/redis/usage/async-redis-db.mdx @@ -11,14 +11,14 @@ import os from agno.agent import Agent from agno.knowledge.knowledge import Knowledge -from agno.vectordb.redis import RedisDB, SearchType +from agno.vectordb.redis import RedisDb, SearchType # Configure Redis connection REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") INDEX_NAME = os.getenv("REDIS_INDEX", "agno_cookbook_vectors") # Initialize Redis Vector DB -vector_db = RedisDB( +vector_db = RedisDb( index_name=INDEX_NAME, redis_url=REDIS_URL, search_type=SearchType.vector, # try SearchType.hybrid for hybrid search diff --git a/knowledge/vector-stores/redis/usage/redis-db.mdx b/knowledge/vector-stores/redis/usage/redis-db.mdx index 041ea9362..7f517e8ca 100644 --- a/knowledge/vector-stores/redis/usage/redis-db.mdx +++ b/knowledge/vector-stores/redis/usage/redis-db.mdx @@ -11,14 +11,14 @@ import os from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.knowledge.knowledge import Knowledge -from agno.vectordb.redis import RedisDB, SearchType +from agno.vectordb.redis import RedisDb, SearchType # Configure Redis connection REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") INDEX_NAME = os.getenv("REDIS_INDEX", "agno_cookbook_vectors") # Initialize Redis Vector DB -vector_db = RedisDB( +vector_db = RedisDb( index_name=INDEX_NAME, redis_url=REDIS_URL, search_type=SearchType.vector, # try SearchType.hybrid for hybrid search diff --git a/models/providers/gateways/cerebras-openai/overview.mdx b/models/providers/gateways/cerebras-openai/overview.mdx index 9690092bf..148f5af19 100644 --- a/models/providers/gateways/cerebras-openai/overview.mdx +++ b/models/providers/gateways/cerebras-openai/overview.mdx @@ -9,7 +9,7 @@ description: Use Cerebras with Agno through an OpenAI-compatible interface. Cerebras also exposes an OpenAI-compatible interface, so you can use it with tools and libraries built for the OpenAI API. -Agno v2.7.2 defaults `CerebrasOpenAI.id` to the retired `llama-4-scout-17b-16e-instruct` model. Set `id="gpt-oss-120b"` or another current [Cerebras model](https://inference-docs.cerebras.ai/models/overview) explicitly. +Cerebras deprecated `llama-4-scout-17b-16e-instruct` on 2025-11-03 — see [Cerebras's deprecation notice](https://inference-docs.cerebras.ai/support/deprecation). Agno v3.0 defaults `CerebrasOpenAI.id` to `gpt-oss-120b`; earlier Agno versions default to the deprecated model, so set `id="gpt-oss-120b"` or another current [Cerebras model](https://inference-docs.cerebras.ai/models/overview) explicitly there. ### Basic Usage @@ -42,12 +42,12 @@ The `CerebrasOpenAI` class accepts the following parameters: | Parameter | Type | Description | Default | | ---------- | ---- | ------------------------------------------------------------- | ------------------------- | -| `id` | str | Model identifier (for example, "gpt-oss-120b") | "llama-4-scout-17b-16e-instruct" | +| `id` | str | Model identifier (for example, "gpt-oss-120b") | "gpt-oss-120b" | | `name` | str | Display name for the model | "CerebrasOpenAI" | | `provider` | str | Provider name | "CerebrasOpenAI" | | `api_key` | str | API key (falls back to CEREBRAS_API_KEY environment variable) | None | | `base_url` | str | URL of the Cerebras OpenAI-compatible endpoint | "https://api.cerebras.ai/v1" | -| `parallel_tool_calls` | Optional[bool] | Whether to run tool calls in parallel (set to False automatically for llama-4-scout-17b-16e-instruct) | None | +| `parallel_tool_calls` | Optional[bool] | Whether to run tool calls in parallel (set to False automatically for `llama-4-scout-17b-16e-instruct`, a model Cerebras has since retired) | None | `CerebrasOpenAI` also supports the parameters of [OpenAI](/reference/models/openai). diff --git a/models/providers/gateways/cerebras/overview.mdx b/models/providers/gateways/cerebras/overview.mdx index 637f59150..dda8b7ae6 100644 --- a/models/providers/gateways/cerebras/overview.mdx +++ b/models/providers/gateways/cerebras/overview.mdx @@ -7,7 +7,7 @@ description: Use Cerebras high-speed inference with Agno agents. [Cerebras Inference](https://inference-docs.cerebras.ai/introduction) provides high-speed, low-latency AI model inference powered by Cerebras Wafer-Scale Engines and CS-3 systems. Agno integrates directly with the Cerebras Python SDK. -Agno v2.7.2 defaults `Cerebras.id` to the retired `llama-4-scout-17b-16e-instruct` model. Set `id="gpt-oss-120b"` or another current [Cerebras model](https://inference-docs.cerebras.ai/models/overview) explicitly. +Cerebras deprecated `llama-4-scout-17b-16e-instruct` on 2025-11-03 — see [Cerebras's deprecation notice](https://inference-docs.cerebras.ai/support/deprecation). Agno v3.0 defaults `Cerebras.id` to `gpt-oss-120b`; earlier Agno versions default to the deprecated model, so set `id="gpt-oss-120b"` or another current [Cerebras model](https://inference-docs.cerebras.ai/models/overview) explicitly there. ## Prerequisites @@ -57,10 +57,10 @@ Cerebras currently serves the following models (see the [model list](https://inf | Parameter | Type | Default | Description | | ---------------------------- | ------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------ | -| `id` | `str` | `"llama-4-scout-17b-16e-instruct"` | The ID of the Cerebras model to use | +| `id` | `str` | `"gpt-oss-120b"` | The ID of the Cerebras model to use | | `name` | `str` | `"Cerebras"` | The name of the model | | `provider` | `str` | `"Cerebras"` | The provider of the model | -| `parallel_tool_calls` | `Optional[bool]` | `None` | Whether to run tool calls in parallel (automatically set to False for llama-4-scout) | +| `parallel_tool_calls` | `Optional[bool]` | `None` | Whether to run tool calls in parallel (automatically set to False for `llama-4-scout-17b-16e-instruct`, a model Cerebras has since retired) | | `max_completion_tokens` | `Optional[int]` | `None` | Maximum number of completion tokens to generate | | `repetition_penalty` | `Optional[float]` | `None` | Penalty for repeating tokens (higher values reduce repetition) | | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output (0.0 to 2.0) | diff --git a/models/providers/gateways/groq/overview.mdx b/models/providers/gateways/groq/overview.mdx index 96dc7654a..b955c5ce6 100644 --- a/models/providers/gateways/groq/overview.mdx +++ b/models/providers/gateways/groq/overview.mdx @@ -8,13 +8,19 @@ Groq provides fast inference endpoints for large language models. See all Groq-supported models [here](https://console.groq.com/docs/models). -- We recommend using `llama-3.3-70b-versatile` for general use. -- We recommend using `llama-3.1-8b-instant` for faster results. -- We recommend using `meta-llama/llama-4-scout-17b-16e-instruct` for image understanding. +- We recommend using `openai/gpt-oss-120b` for general use. +- We recommend using `openai/gpt-oss-20b` for faster results. +- For image understanding, Groq's current options are Preview-tier only — see [Multimodal Support](#multimodal-support) below. + + +Groq shut down `llama-3.3-70b-versatile` and `llama-3.1-8b-instant` on 2026-08-16 for free and developer-tier keys (enterprise customers with a committed-spend contract are unaffected — see [Groq's deprecations page](https://console.groq.com/docs/deprecations)). Agno v3.0 defaults to `openai/gpt-oss-120b`; the old ids return a 404 from Groq. + ## Multimodal Support -With Groq we support `Image` as input. +With Groq we support `Image` as input, on vision-capable models. + +Groq's [vision docs](https://console.groq.com/docs/vision) list the current image-capable models — `qwen/qwen3.6-27b` and `qwen/qwen3.8-27b`. Groq classes both as Preview models, which it describes as suitable for evaluation rather than production and subject to discontinuation at short notice. Groq names `qwen/qwen3.6-27b` as the replacement for the retired `meta-llama/llama-4-scout-17b-16e-instruct`. The default `openai/gpt-oss-120b` does not accept images. ## Authentication @@ -49,7 +55,7 @@ from agno.agent import Agent from agno.models.groq import Groq agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), markdown=True ) @@ -66,7 +72,7 @@ agent.print_response("Share a 2 sentence horror story.") | Parameter | Type | Default | Description | | ------------ | ------------------ | ------------------------------ | --------------------------------------------------------------------- | -| `id` | `str` | `"llama-3.3-70b-versatile"` | The id of the Groq model to use | +| `id` | `str` | `"openai/gpt-oss-120b"` | The id of the Groq model to use | | `name` | `str` | `"Groq"` | The name of the model | | `provider` | `str` | `"Groq"` | The provider of the model | | `api_key` | `Optional[str]` | `None` | The API key for Groq (defaults to GROQ_API_KEY env var) | diff --git a/models/providers/gateways/groq/usage/basic-stream.mdx b/models/providers/gateways/groq/usage/basic-stream.mdx index 864687a94..524f9588a 100644 --- a/models/providers/gateways/groq/usage/basic-stream.mdx +++ b/models/providers/gateways/groq/usage/basic-stream.mdx @@ -11,7 +11,7 @@ Set `stream=True` on `print_response()` to print the response as it arrives. from agno.agent import Agent from agno.models.groq import Groq -agent = Agent(model=Groq(id="llama-3.3-70b-versatile"), markdown=True) +agent = Agent(model=Groq(id="openai/gpt-oss-120b"), markdown=True) # Print the response on the terminal agent.print_response("Share a 2 sentence horror story", stream=True) diff --git a/models/providers/gateways/groq/usage/basic.mdx b/models/providers/gateways/groq/usage/basic.mdx index 4e83f7211..8e63a94ad 100644 --- a/models/providers/gateways/groq/usage/basic.mdx +++ b/models/providers/gateways/groq/usage/basic.mdx @@ -9,7 +9,7 @@ description: Run a Groq agent and print its response. from agno.agent import Agent, RunOutput # noqa from agno.models.groq import Groq -agent = Agent(model=Groq(id="llama-3.3-70b-versatile"), markdown=True) +agent = Agent(model=Groq(id="openai/gpt-oss-120b"), markdown=True) # Get the response in a variable # run: RunOutput = agent.run("Share a 2 sentence horror story") diff --git a/models/providers/gateways/groq/usage/deep-knowledge.mdx b/models/providers/gateways/groq/usage/deep-knowledge.mdx index ad98fb320..22150c68b 100644 --- a/models/providers/gateways/groq/usage/deep-knowledge.mdx +++ b/models/providers/gateways/groq/usage/deep-knowledge.mdx @@ -57,7 +57,7 @@ def create_agent(session_id: Optional[str] = None) -> Agent: return Agent( name="DeepKnowledge", session_id=session_id, - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), description=dedent("""\ You are DeepKnowledge, an advanced reasoning agent designed to provide thorough, well-researched answers to any query by searching your knowledge base. diff --git a/models/providers/gateways/groq/usage/image-agent.mdx b/models/providers/gateways/groq/usage/image-agent.mdx index b7824c010..ccf07f500 100644 --- a/models/providers/gateways/groq/usage/image-agent.mdx +++ b/models/providers/gateways/groq/usage/image-agent.mdx @@ -3,7 +3,11 @@ title: Image Agent description: Send an image to a Groq vision model and stream the description. --- -Pass an `Image` to `print_response()` and use a vision-capable model such as `meta-llama/llama-4-scout-17b-16e-instruct`. +Pass an `Image` to `print_response()` and use a vision-capable model such as `qwen/qwen3.6-27b`. + + +Groq's current image-capable models are Preview tier only — see [Groq's vision docs](https://console.groq.com/docs/vision) for the current list and the [Groq overview](/models/providers/gateways/groq/overview) for details. + ## Code @@ -12,7 +16,7 @@ from agno.agent import Agent from agno.media import Image from agno.models.groq import Groq -agent = Agent(model=Groq(id="meta-llama/llama-4-scout-17b-16e-instruct")) +agent = Agent(model=Groq(id="qwen/qwen3.6-27b")) agent.print_response( "Tell me about this image", diff --git a/models/providers/gateways/groq/usage/knowledge.mdx b/models/providers/gateways/groq/usage/knowledge.mdx index 2c8e96e8a..ac1ed50a4 100644 --- a/models/providers/gateways/groq/usage/knowledge.mdx +++ b/models/providers/gateways/groq/usage/knowledge.mdx @@ -22,7 +22,7 @@ knowledge = Knowledge( knowledge.insert(url="https://agno-public.s3.amazonaws.com/recipes/ThaiRecipes.pdf") agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), knowledge=knowledge, ) agent.print_response("How to make Thai curry?", markdown=True) diff --git a/models/providers/gateways/groq/usage/metrics.mdx b/models/providers/gateways/groq/usage/metrics.mdx index b1c8b9cd1..5241b2e22 100644 --- a/models/providers/gateways/groq/usage/metrics.mdx +++ b/models/providers/gateways/groq/usage/metrics.mdx @@ -13,7 +13,7 @@ from agno.utils.pprint import pprint_run_response from rich.pretty import pprint agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), tools=[YFinanceTools()], markdown=True, ) diff --git a/models/providers/gateways/groq/usage/reasoning-agent.mdx b/models/providers/gateways/groq/usage/reasoning-agent.mdx index 5c3e4c8e5..d81953085 100644 --- a/models/providers/gateways/groq/usage/reasoning-agent.mdx +++ b/models/providers/gateways/groq/usage/reasoning-agent.mdx @@ -11,9 +11,9 @@ from agno.models.groq import Groq # Create a reasoning agent that uses: # - `deepseek-r1-distill-llama-70b` as the reasoning model -# - `llama-3.3-70b-versatile` to generate the final response +# - `openai/gpt-oss-120b` to generate the final response reasoning_agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), reasoning_model=Groq( id="deepseek-r1-distill-llama-70b", temperature=0.6, max_tokens=1024, top_p=0.95 ), diff --git a/models/providers/gateways/groq/usage/structured-output.mdx b/models/providers/gateways/groq/usage/structured-output.mdx index 89bb3c019..ba439b789 100644 --- a/models/providers/gateways/groq/usage/structured-output.mdx +++ b/models/providers/gateways/groq/usage/structured-output.mdx @@ -34,7 +34,7 @@ class MovieScript(BaseModel): ) json_mode_agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), description="You help people write movie scripts.", output_schema=MovieScript, use_json_mode=True, diff --git a/models/providers/gateways/groq/usage/tool-use.mdx b/models/providers/gateways/groq/usage/tool-use.mdx index f8b3c9179..28b595f0d 100644 --- a/models/providers/gateways/groq/usage/tool-use.mdx +++ b/models/providers/gateways/groq/usage/tool-use.mdx @@ -14,7 +14,7 @@ from agno.tools.newspaper4k import Newspaper4kTools from agno.tools.websearch import WebSearchTools agent = Agent( - model=Groq(id="llama-3.3-70b-versatile"), + model=Groq(id="openai/gpt-oss-120b"), tools=[WebSearchTools(), Newspaper4kTools()], description="You are a senior NYT researcher writing an article on a topic.", instructions=[ diff --git a/models/providers/native/anthropic/overview.mdx b/models/providers/native/anthropic/overview.mdx index ce65bb48c..455ed61c3 100644 --- a/models/providers/native/anthropic/overview.mdx +++ b/models/providers/native/anthropic/overview.mdx @@ -12,6 +12,8 @@ Install the Anthropic model extra, set an API key, and pass `Claude` to an `Agen uv pip install -U "agno[anthropic]" ``` +Agno v3.0 requires `anthropic>=0.77.0`, and the extra pins it. That release is the first with the `output_config` request parameter, which Agno now uses for structured output; Agno also routes `temperature`, `top_p`, and `top_k` through `extra_body`, which is how the Claude models keep working on `anthropic` 1.0.0, where `output_format` and those sampling parameters were removed from the SDK's message methods. If you pin the SDK yourself, raise the floor: on an older SDK, a request that sets `output_config` fails at send time with `TypeError: ... unexpected keyword argument 'output_config'`; plain requests are unaffected. + ## Authentication Set the `ANTHROPIC_API_KEY` environment variable. Create a key in the [Claude Console](https://platform.claude.com/settings/keys). @@ -132,10 +134,10 @@ See [prompt caching with Claude](/models/providers/native/anthropic/usage/prompt Pass a Pydantic model as `output_schema` to use Claude's native structured outputs. Anthropic supports structured outputs on Claude Opus 4.1, the Claude 4.5 families, and later models. Claude 3.x, Claude Sonnet 4, and Claude Opus 4 do not support the feature. - Agno v2.7.2 uses Anthropic's legacy `output_format` beta request for this - feature. Anthropic's generally available request shape is - `output_config.format`. The legacy shape remains available during the - transition period. + Agno v3.0 sends structured output through Anthropic's `output_config.format` + request shape, which requires `anthropic>=0.77.0` (the `agno[anthropic]` + extra pins it). Earlier Agno versions used the legacy `output_format` + request, which `anthropic` 1.0.0 removed. ```python diff --git a/models/providers/native/anthropic/usage/structured-output.mdx b/models/providers/native/anthropic/usage/structured-output.mdx index f1fe2c29c..dbdd974e6 100644 --- a/models/providers/native/anthropic/usage/structured-output.mdx +++ b/models/providers/native/anthropic/usage/structured-output.mdx @@ -37,7 +37,7 @@ if __name__ == "__main__": `run.content` is a `MovieScript` instance after Claude returns valid JSON and Agno validates it against the schema. -Agno 2.7.2 translates `output_schema` to Anthropic's legacy-compatible `output_format` request and adds the `structured-outputs-2025-11-13` beta automatically. Anthropic's current direct API uses `output_config.format`; the legacy request remains available during Anthropic's migration period. Let Agno populate the request field when you use `output_schema`. +Agno v3.0 translates `output_schema` to Anthropic's `output_config.format` request shape, which requires `anthropic>=0.77.0` (the `agno[anthropic]` extra pins it). Let Agno populate the request field when you use `output_schema`. Anthropic lists Claude Sonnet 4.6 as supporting structured outputs. Refusals and responses stopped at `max_tokens` can end without a schema-valid result. Anthropic JSON outputs are also incompatible with citations and message prefilling; Agno disables document citations for these requests. diff --git a/models/providers/native/google/gemini-interactions.mdx b/models/providers/native/google/gemini-interactions.mdx index 2b80d4442..5ef2fba2d 100644 --- a/models/providers/native/google/gemini-interactions.mdx +++ b/models/providers/native/google/gemini-interactions.mdx @@ -296,7 +296,7 @@ Read more about Antigravity [here](/models/providers/native/google/usage/interac | Parameter | Type | Default | Description | |-----------|------|---------|-------------| -| `id` | `str` | `"gemini-3-flash-preview"` | The model identifier. Mutually exclusive with `agent`. | +| `id` | `str` | `"gemini-3.7-flash"` | The model identifier. Mutually exclusive with `agent`. | | `agent` | `Optional[str]` | `None` | Managed agent ID (e.g. `"deep-research-preview-04-2026"`, `"antigravity-preview-05-2026"`). Mutually exclusive with `id`. | | `name` | `str` | `"GeminiInteractions"` | The name of the model | | `provider` | `str` | `"Google"` | The provider of the model | diff --git a/models/providers/native/google/overview.mdx b/models/providers/native/google/overview.mdx index b4839ed97..aae0d1650 100644 --- a/models/providers/native/google/overview.mdx +++ b/models/providers/native/google/overview.mdx @@ -430,7 +430,7 @@ Read more about tool use [here](/models/providers/native/google/usage/tool-use). | Parameter | Type | Default | Description | |-----------|------|---------|-------------| -| `id` | `str` | `"gemini-3.5-flash"` | The id of the Gemini model to use | +| `id` | `str` | `"gemini-3.7-flash"` | The id of the Gemini model to use | | `name` | `str` | `"Gemini"` | The name of the model | | `provider` | `str` | `"Google"` | The provider of the model | | `api_key` | `Optional[str]` | `None` | Google API key (defaults to `GOOGLE_API_KEY` env var) | diff --git a/models/providers/native/mistral/overview.mdx b/models/providers/native/mistral/overview.mdx index 18abe0d9a..720304824 100644 --- a/models/providers/native/mistral/overview.mdx +++ b/models/providers/native/mistral/overview.mdx @@ -19,9 +19,11 @@ Mistral has tier-based rate limits. See the [tier docs](https://docs.mistral.ai/ ## Installation ```bash -uv pip install -U mistralai agno +uv pip install -U "mistralai>=2.0.0" agno ``` +Agno v3.0 requires `mistralai>=2.0.0`; the v1 compatibility layer was removed, and the `agno[mistral]` extra pins the floor. With a 1.x SDK installed, the import fails with the generic `` `mistralai` not installed `` message — upgrade the package rather than reinstalling it. + ## Authentication Set your `MISTRAL_API_KEY` environment variable. Get your key from [here](https://console.mistral.ai/api-keys/). diff --git a/models/providers/native/openai/completion/overview.mdx b/models/providers/native/openai/completion/overview.mdx index 3cf9ee546..504cd006e 100644 --- a/models/providers/native/openai/completion/overview.mdx +++ b/models/providers/native/openai/completion/overview.mdx @@ -69,8 +69,8 @@ See the [OpenAI docs](https://platform.openai.com/docs/api-reference/chat/create | `provider` | `str` | `"OpenAI"` | The provider of the model | | `collect_metrics_on_completion` | `bool` | `False` | Collect token metrics only from the final streaming chunk (for providers with cumulative token counts) | | `store` | `Optional[bool]` | `None` | Whether to store the conversation for training purposes | -| `reasoning_effort` | `Optional[str]` | `None` | The reasoning effort level for reasoning models ("low", "medium", "high") | -| `verbosity` | `Optional[Literal["low", "medium", "high"]]` | `None` | Controls verbosity level of reasoning models | +| `reasoning_effort` | `Optional[ReasoningEffort]` | `None` | The reasoning effort level for reasoning models. Named values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; any other string is passed through, and model support varies | +| `verbosity` | `Optional[Verbosity]` | `None` | Controls verbosity level of reasoning models. Named values are `low`, `medium`, and `high`; any other string is passed through | | `metadata` | `Optional[Dict[str, Any]]` | `None` | Developer-defined metadata to associate with the completion | | `frequency_penalty` | `Optional[float]` | `None` | Penalizes new tokens based on their frequency in the text so far (-2.0 to 2.0) | | `logit_bias` | `Optional[Any]` | `None` | Modifies the likelihood of specified tokens appearing in the completion | @@ -86,7 +86,7 @@ See the [OpenAI docs](https://platform.openai.com/docs/api-reference/chat/create | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output (0.0 to 2.0) | | `user` | `Optional[str]` | `None` | A unique identifier representing your end-user | | `top_p` | `Optional[float]` | `None` | Controls diversity via nucleus sampling (0.0 to 1.0) | -| `service_tier` | `Optional[str]` | `None` | Service tier to use ("auto", "default", "flex", "priority") | +| `service_tier` | `Optional[ServiceTier]` | `None` | Service tier to use. Named values are `auto`, `default`, `flex`, `scale`, `priority`, `fast`, and `ultrafast` (`ultrafast` is Responses-only); any other string is passed through. Available tiers vary by account | | `strict_output` | `bool` | `True` | Controls schema adherence for structured outputs | | `extra_headers` | `Optional[Any]` | `None` | Additional headers to include in requests | | `extra_query` | `Optional[Any]` | `None` | Additional query parameters to include in requests | diff --git a/models/providers/native/openai/responses/overview.mdx b/models/providers/native/openai/responses/overview.mdx index f3c7564c3..a82ec93bd 100644 --- a/models/providers/native/openai/responses/overview.mdx +++ b/models/providers/native/openai/responses/overview.mdx @@ -66,15 +66,15 @@ See the [OpenAI Responses docs](https://platform.openai.com/docs/api-reference/r | `metadata` | `Optional[Dict[str, Any]]` | `None` | Developer-defined metadata to associate with the response | | `parallel_tool_calls` | `Optional[bool]` | `None` | Whether to enable parallel function calling | | `reasoning` | `Optional[Dict[str, Any]]` | `None` | Reasoning configuration for reasoning models | -| `verbosity` | `Optional[Literal["low", "medium", "high"]]` | `None` | Controls verbosity of the model's output | -| `reasoning_effort` | `Optional[Literal["minimal", "low", "medium", "high"]]` | `None` | Reasoning effort level for reasoning models | -| `reasoning_summary` | `Optional[Literal["auto", "concise", "detailed"]]` | `None` | Level of detail for reasoning summaries | +| `verbosity` | `Optional[Verbosity]` | `None` | Controls verbosity of the model's output. Named values are `low`, `medium`, and `high`; any other string is passed through | +| `reasoning_effort` | `Optional[ReasoningEffort]` | `None` | Reasoning effort level for reasoning models. Named values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; any other string is passed through, and model support varies | +| `reasoning_summary` | `Optional[ReasoningSummary]` | `None` | Level of detail for reasoning summaries. Named values are `auto`, `concise`, and `detailed`; any other string is passed through | | `store` | `Optional[bool]` | `None` | Whether to store the response for later retrieval | | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output (0.0 to 2.0) | | `top_p` | `Optional[float]` | `None` | Controls diversity via nucleus sampling (0.0 to 1.0) | | `truncation` | `Optional[Literal["auto", "disabled"]]` | `None` | Truncation strategy when context exceeds the window | | `user` | `Optional[str]` | `None` | A unique identifier representing your end-user | -| `service_tier` | `Optional[Literal["auto", "default", "flex", "priority"]]` | `None` | Service tier to use for the request | +| `service_tier` | `Optional[ServiceTier]` | `None` | Service tier to use for the request. Named values are `auto`, `default`, `flex`, `scale`, `priority`, `fast`, and `ultrafast` (`ultrafast` is Responses-only); any other string is passed through. Available tiers vary by account | | `strict_output` | `bool` | `True` | Controls schema adherence for structured outputs | | `background` | `Optional[bool]` | `None` | Enables background mode for long-running tasks. Not supported for streaming | | `background_poll_interval` | `float` | `2.0` | Interval in seconds between polling attempts in background mode | diff --git a/other/v3-changelog.mdx b/other/v3-changelog.mdx index 7963d3b4e..cc7e3463b 100644 --- a/other/v3-changelog.mdx +++ b/other/v3-changelog.mdx @@ -64,6 +64,10 @@ The major changes are: - `LanceDb`: `use_tantivy` is removed; passing it now raises a `TypeError`. + - The Redis vector store is renamed `RedisDB` -> `RedisDb`; the old spelling + keeps working as a deprecated alias, with no warning emitted. + `RedisVectorDb` is also exported, to disambiguate from the + `agno.db.redis.RedisDb` storage adapter. - On schema-based stores, searching a pre-v3 vector table with a `user_id` raises a `ValueError` directing you to the vector database migration, instead of silently returning empty results. Schemaless stores (Qdrant, @@ -179,7 +183,11 @@ The major changes are: - `MCPToolbox`: `auth_tokens` and `auth_headers` removed. Use `auth_token_getters`. - - Toolkits have an `id`, used by AgentOS to reference tools stably. + - Toolkits have a stable `id`, derived from `name` when not passed + (lower-cased, spaces and underscores replaced by hyphens). It is reserved + for future use: in v3.0 nothing reads it except `repr()`. Because `id` is + the second positional argument, positional `tools` no longer works — pass + `tools=` by keyword. @@ -292,6 +300,16 @@ The major changes are: - `Cerebras` and `CerebrasOpenAI` default to `gpt-oss-120b`, replacing `llama-4-scout-17b-16e-instruct`. + - `Groq` defaults to `openai/gpt-oss-120b`, replacing + `llama-3.3-70b-versatile`, which Groq shut down on 2026-08-16 for free and + developer-tier keys. The old id now returns a 404 from Groq. + - `Gemini` defaults to `gemini-3.7-flash` (was `gemini-3.5-flash`), and + `GeminiInteractions` defaults to `gemini-3.7-flash` (was + `gemini-3-flash-preview`). Pin the old id explicitly if you depend on it. + - Claude models work with `anthropic` 1.0.0: structured output is sent + through `output_config`, and `temperature`/`top_p`/`top_k` travel in + `extra_body`. `agno[anthropic]` now requires `anthropic>=0.77.0`, the + first SDK release with `output_config`; raise your own pin if you set one. - OpenAI `reasoning_effort`, `reasoning_summary`, `service_tier` and `verbosity` accept the full set of API values (including `none`, `xhigh`, `max`, `scale`, `fast`, `ultrafast`) and any future string. This widens the diff --git a/other/v3-migration.mdx b/other/v3-migration.mdx index c6fecf15d..74610af4f 100644 --- a/other/v3-migration.mdx +++ b/other/v3-migration.mdx @@ -351,7 +351,13 @@ Two API changes come with it: - **AgentOS metadata routes**: `GET /models` was removed (its data moved into `GET /config` under `available_models`), and `GET /` is now a minimal landing response. `GET /info` is the single unauthenticated metadata endpoint. -- **Toolkits have an `id`**, used by AgentOS to reference tools stably. +- **`Toolkit` gained an `id` parameter** as the second positional argument, + after `name`. Positional `tools` no longer works: `Toolkit("my_tools", [my_fn])` + now assigns the list to `id` and registers no tools, without an error. Pass + tools by keyword — `Toolkit(name="my_tools", tools=[my_fn])`. Built-in + toolkits are unaffected. When not passed, `id` is derived from `name` + (lower-cased, spaces and underscores replaced by hyphens); it is reserved — + nothing reads it in v3.0 except `repr()`. - **Schedule provenance columns**: the schedules table gains eight nullable columns (`managed_by`, `target_type`, `target_id`, `created_by_run_id`, `created_by_session_id`, `updated_by_run_id`, `updated_by_session_id`, @@ -420,6 +426,22 @@ Two API changes come with it: - **Cerebras default model**: `Cerebras` and `CerebrasOpenAI` now default to `gpt-oss-120b` instead of `llama-4-scout-17b-16e-instruct`. Pin the old id explicitly if you depend on it. +- **Groq default model**: `Groq` now defaults to `openai/gpt-oss-120b`. The old + default `llama-3.3-70b-versatile` was shut down by Groq on 2026-08-16 for + free and developer-tier keys, so pinning it returns a 404 — move to + `openai/gpt-oss-120b` or another current Groq model. +- **Gemini default model**: `Gemini` now defaults to `gemini-3.7-flash` (was + `gemini-3.5-flash`) and `GeminiInteractions` to `gemini-3.7-flash` (was + `gemini-3-flash-preview`). Pin the old id explicitly if you depend on it. +- **`agno[anthropic]` pins `anthropic>=0.77.0`**: structured output now rides + in `output_config`, which that SDK release introduced. If you pin the SDK + yourself, raise the floor; on an older SDK, a request that sets + `output_config` fails at send time with + `TypeError: ... unexpected keyword argument 'output_config'`. +- **Redis vector store rename**: `RedisDB` -> `RedisDb`. The old spelling still + works as a deprecated alias with no warning. Use `RedisVectorDb` to + disambiguate from the `agno.db.redis.RedisDb` storage adapter when both are + imported in one module. - **`agno[postgres]` installs a working driver**: the extra previously installed `psycopg-binary` only, so `PostgresDb` failed with `ModuleNotFoundError: No module named 'sqlalchemy'`. It now pulls `psycopg` @@ -462,6 +484,10 @@ Rename these imports and modules wherever they appear: - from agno.models.metrics import Metrics -> from agno.metrics import RunMetrics - SeltzTools kwarg max_documents= -> max_results= - BrandfetchTools: drop any async_tools= argument +- from agno.vectordb.redis import RedisDB -> RedisDb (the old alias still + works; use RedisVectorDb when agno.db.redis.RedisDb is imported in the same module) +- Toolkit("name", [fns]) with positional tools -> Toolkit(name="name", tools=[fns]) + (JUDGMENT: positional tools now binds to the new id parameter and registers nothing) - LanceDb: drop any use_tantivy= argument - AgentOS(enable_mcp_server=X, mcp_config=Y) -> AgentOS(mcp_server=Y or X) diff --git a/reasoning/usage/tools/groq-reasoning-tools.mdx b/reasoning/usage/tools/groq-reasoning-tools.mdx index b63e807d6..694aa768b 100644 --- a/reasoning/usage/tools/groq-reasoning-tools.mdx +++ b/reasoning/usage/tools/groq-reasoning-tools.mdx @@ -20,7 +20,7 @@ description: "Run Llama 4 Scout on Groq with ReasoningTools and WebSearchTools t from agno.tools.websearch import WebSearchTools thinking_llama = Agent( - model=Groq(id="meta-llama/llama-4-scout-17b-16e-instruct"), + model=Groq(id="openai/gpt-oss-120b"), tools=[ ReasoningTools(), WebSearchTools(), diff --git a/reference/models/gemini.mdx b/reference/models/gemini.mdx index 2399191a5..8b4c14825 100644 --- a/reference/models/gemini.mdx +++ b/reference/models/gemini.mdx @@ -10,7 +10,7 @@ The Gemini model provides access to Google's Gemini models. | Parameter | Type | Default | Description | | ------------------------------- | ----------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------- | -| `id` | `str` | `"gemini-3.5-flash"` | The id of the Gemini model to use | +| `id` | `str` | `"gemini-3.7-flash"` | The id of the Gemini model to use | | `name` | `str` | `"Gemini"` | The name of the model | | `provider` | `str` | `"Google"` | The provider of the model | | `function_declarations` | `Optional[List[Any]]` | `None` | Function declarations to make available to the model | diff --git a/reference/models/groq.mdx b/reference/models/groq.mdx index e15062b1f..386e58558 100644 --- a/reference/models/groq.mdx +++ b/reference/models/groq.mdx @@ -10,7 +10,7 @@ The Groq model provides access to Groq's high-performance language models. | Parameter | Type | Default | Description | | ------------ | ------------------ | ------------------------------ | --------------------------------------------------------------------- | -| `id` | `str` | `"llama-3.3-70b-versatile"` | The id of the Groq model to use | +| `id` | `str` | `"openai/gpt-oss-120b"` | The id of the Groq model to use | | `name` | `str` | `"Groq"` | The name of the model | | `provider` | `str` | `"Groq"` | The provider of the model | | `frequency_penalty` | `Optional[float]` | `None` | Penalizes new tokens based on their frequency in the text so far | diff --git a/reference/models/open-responses.mdx b/reference/models/open-responses.mdx index 71f9a1796..5c8e6cafd 100644 --- a/reference/models/open-responses.mdx +++ b/reference/models/open-responses.mdx @@ -41,15 +41,15 @@ Providers that implement this spec include Ollama (v0.13.3+) and OpenRouter. Pro | `metadata` | `Optional[Dict[str, Any]]` | `None` | Developer-defined metadata to associate with the response | | `parallel_tool_calls` | `Optional[bool]` | `None` | Whether the model can run tool calls in parallel | | `reasoning` | `Optional[Dict[str, Any]]` | `None` | Reasoning configuration (e.g. `{"enabled": True}`) | -| `verbosity` | `Optional[Literal["low", "medium", "high"]]` | `None` | Verbosity level of the model response | -| `reasoning_effort` | `Optional[Literal["minimal", "low", "medium", "high"]]` | `None` | Reasoning effort for reasoning models | -| `reasoning_summary` | `Optional[Literal["auto", "concise", "detailed"]]` | `None` | Level of detail for reasoning summaries | +| `verbosity` | `Optional[Verbosity]` | `None` | Verbosity level of the model response. Named values are `low`, `medium`, and `high`; any other string is passed through | +| `reasoning_effort` | `Optional[ReasoningEffort]` | `None` | Reasoning effort for reasoning models. Named values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; any other string is passed through, and model support varies | +| `reasoning_summary` | `Optional[ReasoningSummary]` | `None` | Level of detail for reasoning summaries. Named values are `auto`, `concise`, and `detailed`; any other string is passed through | | `store` | `Optional[bool]` | `False` | Whether to store the response on the provider side. Disabled by default for compatible providers | | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output | | `top_p` | `Optional[float]` | `None` | Controls diversity via nucleus sampling | | `truncation` | `Optional[Literal["auto", "disabled"]]` | `None` | Truncation strategy when the context window is exceeded | | `user` | `Optional[str]` | `None` | A unique identifier representing your end-user | -| `service_tier` | `Optional[Literal["auto", "default", "flex", "priority"]]` | `None` | Processing tier for the request | +| `service_tier` | `Optional[ServiceTier]` | `None` | Processing tier for the request. Named values are `auto`, `default`, `flex`, `scale`, `priority`, `fast`, and `ultrafast` (`ultrafast` is Responses-only); any other string is passed through. Available tiers vary by account | | `strict_output` | `bool` | `True` | Guarantees schema adherence for structured outputs. When `False`, the schema is followed as a guide and output may deviate | | `background` | `Optional[bool]` | `None` | Enables background mode for long-running tasks. The API returns immediately and the response is polled until completion. Not supported for streaming | | `background_poll_interval` | `float` | `2.0` | Interval in seconds between polling attempts in background mode | diff --git a/reference/models/openai-like.mdx b/reference/models/openai-like.mdx index ccd97d5f2..7c51ebfe5 100644 --- a/reference/models/openai-like.mdx +++ b/reference/models/openai-like.mdx @@ -28,8 +28,8 @@ description: "Configuration reference for OpenAILike, the base class for provide | Parameter | Type | Default | Description | | ----------------------- | --------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- | | `store` | `Optional[bool]` | `None` | Whether to store the output of the request on the provider side | -| `reasoning_effort` | `Optional[str]` | `None` | Reasoning effort for reasoning models ("low", "medium", "high") | -| `verbosity` | `Optional[Literal["low", "medium", "high"]]` | `None` | Verbosity level of the model response | +| `reasoning_effort` | `Optional[ReasoningEffort]` | `None` | Reasoning effort for reasoning models. Named values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; any other string is passed through, and model support varies | +| `verbosity` | `Optional[Verbosity]` | `None` | Verbosity level of the model response. Named values are `low`, `medium`, and `high`; any other string is passed through | | `metadata` | `Optional[Dict[str, Any]]` | `None` | Developer-defined metadata to associate with the completion | | `frequency_penalty` | `Optional[float]` | `None` | Penalizes new tokens based on their frequency in the text so far (-2.0 to 2.0) | | `logit_bias` | `Optional[Any]` | `None` | Modifies the likelihood of specified tokens appearing in the completion | @@ -45,7 +45,7 @@ description: "Configuration reference for OpenAILike, the base class for provide | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output | | `user` | `Optional[str]` | `None` | A unique identifier representing your end-user | | `top_p` | `Optional[float]` | `None` | Controls diversity via nucleus sampling | -| `service_tier` | `Optional[str]` | `None` | Processing tier for the request ("auto", "default", "flex", "priority") | +| `service_tier` | `Optional[ServiceTier]` | `None` | Processing tier for the request. Named values are `auto`, `default`, `flex`, `scale`, `priority`, `fast`, and `ultrafast` (`ultrafast` is Responses-only); any other string is passed through. Available tiers vary by account | | `strict_output` | `bool` | `True` | Guarantees schema adherence for structured outputs. When `False`, the schema is followed as a guide and output may deviate | | `extra_headers` | `Optional[Any]` | `None` | Additional headers to include in requests | | `extra_query` | `Optional[Any]` | `None` | Additional query parameters to include in requests | diff --git a/reference/models/openai.mdx b/reference/models/openai.mdx index 0a206befb..812e0d019 100644 --- a/reference/models/openai.mdx +++ b/reference/models/openai.mdx @@ -15,8 +15,8 @@ The OpenAIChat model provides access to OpenAI models using the Chat Completions | `provider` | `str` | `"OpenAI"` | The provider of the model | | `collect_metrics_on_completion` | `bool` | `False` | Collect token metrics only from the final streaming chunk (for providers with cumulative token counts) | | `store` | `Optional[bool]` | `None` | Whether to store the conversation for training purposes | -| `reasoning_effort` | `Optional[str]` | `None` | Model-dependent reasoning effort. API values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; model support varies. See [Create chat completion](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create). | -| `verbosity` | `Optional[Literal["low", "medium", "high"]]` | `None` | Controls verbosity level of reasoning models | +| `reasoning_effort` | `Optional[ReasoningEffort]` | `None` | Model-dependent reasoning effort. Named values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; any other string is passed through, and model support varies. See [Create chat completion](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create). | +| `verbosity` | `Optional[Verbosity]` | `None` | Controls verbosity level of reasoning models. Named values are `low`, `medium`, and `high`; any other string is passed through | | `metadata` | `Optional[Dict[str, Any]]` | `None` | Developer-defined metadata to associate with the completion | | `frequency_penalty` | `Optional[float]` | `None` | Penalizes new tokens based on their frequency in the text so far (-2.0 to 2.0) | | `logit_bias` | `Optional[Any]` | `None` | Modifies the likelihood of specified tokens appearing in the completion | @@ -32,7 +32,7 @@ The OpenAIChat model provides access to OpenAI models using the Chat Completions | `temperature` | `Optional[float]` | `None` | Controls randomness in the model's output (0.0 to 2.0) | | `user` | `Optional[str]` | `None` | A unique identifier representing your end-user | | `top_p` | `Optional[float]` | `None` | Controls diversity via nucleus sampling (0.0 to 1.0) | -| `service_tier` | `Optional[str]` | `None` | Service tier to use ("auto", "default", "flex", "priority") | +| `service_tier` | `Optional[ServiceTier]` | `None` | Service tier to use. Named values are `auto`, `default`, `flex`, `scale`, `priority`, `fast`, and `ultrafast` (`ultrafast` is Responses-only); any other string is passed through. Available tiers vary by account | | `strict_output` | `bool` | `True` | Controls schema adherence for structured outputs | | `extra_headers` | `Optional[Any]` | `None` | Additional headers to include in requests | | `extra_query` | `Optional[Any]` | `None` | Additional query parameters to include in requests | diff --git a/reference/run/metrics.mdx b/reference/run/metrics.mdx index a1c7ec659..0f296c321 100644 --- a/reference/run/metrics.mdx +++ b/reference/run/metrics.mdx @@ -58,7 +58,6 @@ The `details` dictionary uses model type strings as keys. Each key maps to a lis | `"memory_model"` | Memory model | | `"reasoning_model"` | Reasoning model | | `"session_summary_model"` | Session summary model | -| `"culture_model"` | Culture model | | `"learning_model"` | Learning model | | `"compression_model"` | Compression model | | `"followup_model"` | Followup model | @@ -66,9 +65,9 @@ The `details` dictionary uses model type strings as keys. Each key maps to a lis Eval agent metrics are prefixed with `eval_`. If an eval agent uses model types `"model"` and `"output_model"`, the details keys become `"eval_model"` and `"eval_output_model"`. - -`Metrics` is preserved as a backward-compatible alias for `RunMetrics`. Both `from agno.metrics import Metrics` and `from agno.models.metrics import Metrics` still work. - + +The `Metrics` alias and the `agno.models.metrics` module were removed in Agno v3.0. Import metric classes from `agno.metrics` — for example, `from agno.metrics import RunMetrics`. + ## WorkflowMetrics diff --git a/reference/tools/decorator.mdx b/reference/tools/decorator.mdx index ef68fd65f..fb355c9e7 100644 --- a/reference/tools/decorator.mdx +++ b/reference/tools/decorator.mdx @@ -15,7 +15,9 @@ from agno.tools import tool | Parameter | Type | Description | |-----------|------|-------------| | `name` | `str` | Override for the function name | +| `title` | `str` | Human-readable display title for the tool. Not sent to the model; read when the tool is published over AgentOS MCP | | `description` | `str` | Override for the function description | +| `annotations` | `Dict[str, Any]` | MCP tool annotations. Allowed keys: `title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`. An unknown key raises `ValueError`; hints must be booleans and `title` a string. Not sent to the model; read when the tool is published over AgentOS MCP | | `strict` | `bool` | If True, enforces strict parameter checking on the function schema | | `instructions` | `str` | Instructions for using the tool | | `add_instructions` | `bool` | If True, adds the tool instructions to the system message (default: True) | diff --git a/reference/tools/toolkit.mdx b/reference/tools/toolkit.mdx index 2d2eb61e9..df0d7e58e 100644 --- a/reference/tools/toolkit.mdx +++ b/reference/tools/toolkit.mdx @@ -19,6 +19,7 @@ from agno.tools.toolkit import Toolkit | Parameter | Type | Description | |-----------|------|-------------| | `name` | `str` | A descriptive name for the toolkit. | +| `id` | `Optional[str]` | Reserved stable identifier for the toolkit. Defaults to `name` lower-cased with spaces and underscores replaced by hyphens (`"My Toolkit"` → `"my-toolkit"`), the same derivation Agent, Team, and Workflow use. Shown in `repr(toolkit)`; nothing else reads it in Agno v3.0 — AgentOS and the registry key toolkits by `name`. | | `tools` | `Sequence[Union[Callable, Function]]` | List of callables or `Function` objects (from the `@tool` decorator) to include in the toolkit. | | `async_tools` | `Sequence[tuple[Callable, str]]` | List of `(async_callable, tool_name)` tuples registering async variants whose names differ from the sync methods, e.g. `[(self.ascreenshot, "screenshot")]`. | | `instructions` | `str` | Instructions for using the toolkit. Can be added to agent context. | @@ -35,6 +36,10 @@ from agno.tools.toolkit import Toolkit | `timeout` | `Optional[int]` | Timeout in seconds for the toolkit's primary I/O operation (HTTP request, SDK call, sandbox execution). Subclasses forward their own `timeout` via `super().__init__(timeout=...)`. | | `auto_register` | `bool` | Whether to automatically register all tools in the toolkit upon initialization. | + +In Agno v3.0, `id` is the second positional argument, after `name`. Positional `tools` no longer works: `Toolkit("my_tools", [my_fn])` assigns the list to `id` and registers no tools, without an error. Pass tools by keyword — `Toolkit(name="my_tools", tools=[my_fn])`. Built-in toolkits are unaffected. + + ## Usage Examples ### Basic Toolkit diff --git a/tools/mcp/dynamic-headers.mdx b/tools/mcp/dynamic-headers.mdx index eb15f784f..f7ab71ba3 100644 --- a/tools/mcp/dynamic-headers.mdx +++ b/tools/mcp/dynamic-headers.mdx @@ -143,19 +143,21 @@ if __name__ == "__main__": 3. You can check the logs of your MCP server to see the headers that were sent. -## Usage with MultiMCPTools +## Usage with Multiple Servers -Dynamic headers work the same way with `MultiMCPTools`: +With multiple servers, pass a `header_provider` to each `MCPTools` instance that needs one: ```python -from agno.tools.mcp import MultiMCPTools - -mcp_tools = MultiMCPTools( - urls=[ - "http://server1.example.com/mcp", - "http://server2.example.com/mcp", - ], - urls_transports=["streamable-http", "streamable-http"], - header_provider=header_provider, # Applied to all servers +from agno.tools.mcp import MCPTools + +server1_tools = MCPTools( + url="http://server1.example.com/mcp", + transport="streamable-http", + header_provider=header_provider, +) +server2_tools = MCPTools( + url="http://server2.example.com/mcp", + transport="streamable-http", + header_provider=header_provider, ) ``` \ No newline at end of file diff --git a/tools/mcp/multiple-servers.mdx b/tools/mcp/multiple-servers.mdx index 2111c4861..61f12e93b 100644 --- a/tools/mcp/multiple-servers.mdx +++ b/tools/mcp/multiple-servers.mdx @@ -1,17 +1,13 @@ --- title: Multiple MCP Servers -description: Connect an Agent to multiple MCP servers with separate MCPTools instances or MultiMCPTools. +description: Connect an Agent to multiple MCP servers with one MCPTools instance per server. --- -Agno's MCP integration supports connecting an Agent to multiple MCP servers at once. +Agno's MCP integration supports connecting an Agent to multiple MCP servers at once: create one `MCPTools` instance per server and pass them all to the Agent. -There are two approaches to this: -1. Using multiple `MCPTools` instances -2. Using a single `MultiMCPTools` instance - - -`MultiMCPTools` is deprecated and will be removed in a future version. Use multiple `MCPTools` instances instead. - + +`MultiMCPTools` was removed in Agno v3.0. Importing it raises an `ImportError`; use one `MCPTools` instance per server, as below. Note that `env=` is per-instance — pass it to the server that needs it. + ## Prerequisites @@ -30,11 +26,10 @@ Export the keys used by the examples you run: ```bash export OPENAI_API_KEY="your_openai_api_key_here" export GOOGLE_MAPS_API_KEY="your_google_maps_api_key_here" -export BRAVE_API_KEY="your_brave_api_key_here" ``` -The `@modelcontextprotocol/server-google-maps` and `@modelcontextprotocol/server-brave-search` npm packages are deprecated and no longer supported. The snippets below document these legacy servers. Use maintained MCP servers for new projects. +The `@modelcontextprotocol/server-google-maps` npm package is deprecated and no longer supported. The snippets below document this legacy server. Use maintained MCP servers for new projects. ## Using multiple `MCPTools` instances @@ -87,116 +82,18 @@ if __name__ == "__main__": ) ``` -## Using a single `MultiMCPTools` instance - -```python multiple_mcp_servers.py -import asyncio -import os -from datetime import date, timedelta - -from agno.agent import Agent -from agno.tools.mcp import MultiMCPTools - - -async def run_agent(message: str) -> None: - """Run the Airbnb and Google Maps agent with the given message.""" - - env = { - **os.environ, - "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"), - } - - # Initialize and connect to multiple MCP servers - mcp_tools = MultiMCPTools( - commands=[ - "npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt", - "npx -y @modelcontextprotocol/server-google-maps", - ], - env=env, - ) - await mcp_tools.connect() +## Handling Connection Failures - try: - agent = Agent( - tools=[mcp_tools], - markdown=True, - ) - - await agent.aprint_response(message, stream=True) - finally: - # Always close the connection when done - await mcp_tools.close() - - -# Example usage -if __name__ == "__main__": - check_in = date.today() + timedelta(days=30) - check_out = check_in + timedelta(days=3) - # Pull request example - asyncio.run( - run_agent( - f"What listings are available in Cape Town for 2 people " - f"from {check_in.isoformat()} to {check_out.isoformat()}?" - ) - ) -``` - -### Allowing partial failures with `MultiMCPTools` - -If you are connecting to multiple MCP servers using the `MultiMCPTools` class, an error will be raised by default if connection to any MCP server fails. - -If you want to avoid raising in that case, you can set the `allow_partial_failure` parameter to `True`. - -This is useful if you are connecting to MCP servers that are not always available, and don't want to exit your program if one of the servers is not available. +`connect()` does not raise when a server is unreachable: it logs the error and leaves the instance uninitialized, so the Agent can still run with the servers that did connect. To fail fast when a server is required, check `initialized` after connecting: ```python -import asyncio -from datetime import date -from os import getenv - -from agno.agent import Agent -from agno.tools.mcp import MultiMCPTools - - -async def run_agent(message: str) -> None: - # Initialize the MCP tools - mcp_tools = MultiMCPTools( - [ - "npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt", - "npx -y @modelcontextprotocol/server-brave-search", - ], - env={ - "BRAVE_API_KEY": getenv("BRAVE_API_KEY"), - }, - timeout_seconds=30, - # Set the allow_partial_failure to True to allow for partial failure connecting to the MCP servers - allow_partial_failure=True, - ) - - # Connect to the MCP servers - await mcp_tools.connect() - - # Use the MCP tools with an Agent - agent = Agent( - tools=[mcp_tools], - markdown=True, - ) - await agent.aprint_response(message) - - # Close the MCP connection - await mcp_tools.close() - - -# Example usage -if __name__ == "__main__": - asyncio.run( - run_agent( - f"What listings are available in Barcelona on {date.today().isoformat()}?" - ) - ) - asyncio.run(run_agent("What's the fastest way to get to Barcelona from London?")) +await airbnb_tools.connect() +if not airbnb_tools.initialized: + raise RuntimeError("Airbnb MCP server is unavailable") ``` +Using `async with MCPTools(...)` as a context manager instead raises on connection failure. + ## Avoiding tool name collisions When using multiple MCP servers, you may encounter tool name collisions. This often happens when the same tool is available in multiple of the servers you are using. diff --git a/tools/mcp/overview.mdx b/tools/mcp/overview.mdx index 1fd05f4c9..2c7d90c68 100644 --- a/tools/mcp/overview.mdx +++ b/tools/mcp/overview.mdx @@ -172,7 +172,7 @@ This has an impact on performance and is not recommended for production use. ### Using Async Context Manager -If you prefer, you can also use `MCPTools` or `MultiMCPTools` as async context managers for automatic resource cleanup: +If you prefer, you can also use `MCPTools` as an async context manager for automatic resource cleanup: ```python async with MCPTools(command="uvx mcp-server-git") as mcp_tools: @@ -194,7 +194,7 @@ This is the recommended way to manage the connection lifecycle of the MCP server ## Connection Refresh -You can set `refresh_connection` on the `MCPTools` and `MultiMCPTools` instances to refresh the connection to the MCP server on each run. +You can set `refresh_connection` on an `MCPTools` instance to refresh the connection to the MCP server on each run. ```python mcp_tools = MCPTools(command="uvx mcp-server-git", refresh_connection=True) @@ -221,7 +221,7 @@ Transports in the Model Context Protocol (MCP) define how messages are sent and - [SSE](https://modelcontextprotocol.io/docs/basics/transports#server-sent-events-sse) -> See the [SSE transport documentation](/tools/mcp/transports/sse) -The stdio (standard input/output) transport is the default one in Agno's `MCPTools` and `MultiMCPTools`. +The stdio (standard input/output) transport is the default one in Agno's `MCPTools`. diff --git a/tools/mcp/server-params.mdx b/tools/mcp/server-params.mdx index ea7a467dc..efc2b4d77 100644 --- a/tools/mcp/server-params.mdx +++ b/tools/mcp/server-params.mdx @@ -1,6 +1,6 @@ --- title: Understanding Server Parameters -description: Understanding how to configure the server parameters for the MCPTools and MultiMCPTools classes +description: Understanding how to configure the server parameters for the MCPTools class --- diff --git a/tools/mcp/transports/sse.mdx b/tools/mcp/transports/sse.mdx index d9de263e9..e9f8df83e 100644 --- a/tools/mcp/transports/sse.mdx +++ b/tools/mcp/transports/sse.mdx @@ -61,10 +61,6 @@ finally: Set up a simple local server and connect to it using the SSE transport: - -The example below also shows `MultiMCPTools`, which is deprecated and will be removed in a future version. Use multiple `MCPTools` instances instead. - - ```python sse_server.py @@ -94,7 +90,7 @@ The example below also shows `MultiMCPTools`, which is deprecated and will be re from agno.agent import Agent from agno.models.openai import OpenAIResponses - from agno.tools.mcp import MCPTools, MultiMCPTools + from agno.tools.mcp import MCPTools # This is the URL of the MCP server we want to use. server_url = "http://localhost:8000/sse" @@ -116,32 +112,32 @@ The example below also shows `MultiMCPTools`, which is deprecated and will be re await mcp_tools.close() - # Using MultiMCPTools, we can connect to multiple MCP servers at once, even if they use different transports. - # In this example we connect to both our example server (SSE transport), and a different server (stdio transport). - async def run_agent_with_multimcp(message: str) -> None: + # With one MCPTools instance per server, we can connect to multiple MCP servers at once, + # even if they use different transports. In this example we connect to both our example + # server (SSE transport) and a different server (stdio transport). + async def run_agent_with_multiple_servers(message: str) -> None: # Initialize and connect to multiple MCP servers with different transports - mcp_tools = MultiMCPTools( - commands=["npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt"], - urls=[server_url], - urls_transports=["sse"], - ) - await mcp_tools.connect() + airbnb_tools = MCPTools(command="npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt") + calendar_tools = MCPTools(transport="sse", url=server_url) + await airbnb_tools.connect() + await calendar_tools.connect() try: agent = Agent( model=OpenAIResponses(id="gpt-5.2"), - tools=[mcp_tools], + tools=[airbnb_tools, calendar_tools], markdown=True, ) await agent.aprint_response(input=message, stream=True, markdown=True) finally: - await mcp_tools.close() + await airbnb_tools.close() + await calendar_tools.close() if __name__ == "__main__": asyncio.run(run_agent("Do I have any birthdays this week?")) asyncio.run( - run_agent_with_multimcp( + run_agent_with_multiple_servers( "Can you check when is my mom's birthday, and if there are any AirBnb listings in SF for two people for that day?" ) ) diff --git a/tools/mcp/transports/stdio.mdx b/tools/mcp/transports/stdio.mdx index dbb96e8fe..ba061a379 100644 --- a/tools/mcp/transports/stdio.mdx +++ b/tools/mcp/transports/stdio.mdx @@ -52,12 +52,7 @@ finally: ``` -You can also use multiple MCP servers at once, with the `MultiMCPTools` class. For example: - - -`MultiMCPTools` is deprecated and will be removed in a future version. Use multiple `MCPTools` instances instead. - - +You can also use multiple MCP servers at once, with one `MCPTools` instance per server. For example: ```python import asyncio @@ -65,7 +60,7 @@ import os from datetime import date, timedelta from agno.agent import Agent -from agno.tools.mcp import MultiMCPTools +from agno.tools.mcp import MCPTools async def run_agent(message: str) -> None: @@ -76,32 +71,28 @@ async def run_agent(message: str) -> None: } # Initialize and connect to multiple MCP servers - mcp_tools = MultiMCPTools( - commands=[ - "npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt", - "npx -y @modelcontextprotocol/server-google-maps", - ], - env=env, - ) - await mcp_tools.connect() + airbnb_tools = MCPTools(command="npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt") + google_maps_tools = MCPTools(command="npx -y @modelcontextprotocol/server-google-maps", env=env) + await airbnb_tools.connect() + await google_maps_tools.connect() try: agent = Agent( - tools=[mcp_tools], + tools=[airbnb_tools, google_maps_tools], markdown=True, ) await agent.aprint_response(message, stream=True) finally: - # Always close the connection when done - await mcp_tools.close() + # Always close the connections when done + await airbnb_tools.close() + await google_maps_tools.close() # Example usage if __name__ == "__main__": check_in = date.today() + timedelta(days=30) check_out = check_in + timedelta(days=3) - # Pull request example asyncio.run( run_agent( f"What listings are available in Cape Town for 2 people " diff --git a/tools/mcp/transports/streamable_http.mdx b/tools/mcp/transports/streamable_http.mdx index 5352670e5..ddf07c346 100644 --- a/tools/mcp/transports/streamable_http.mdx +++ b/tools/mcp/transports/streamable_http.mdx @@ -58,11 +58,6 @@ finally: Set up a simple local server and connect to it using the Streamable HTTP transport: - -The example below also shows `MultiMCPTools`, which is deprecated and will be removed in a future version. Use multiple `MCPTools` instances instead. - - - ```python streamable_http_server.py @@ -92,7 +87,7 @@ The example below also shows `MultiMCPTools`, which is deprecated and will be re from agno.agent import Agent from agno.models.openai import OpenAIResponses - from agno.tools.mcp import MCPTools, MultiMCPTools + from agno.tools.mcp import MCPTools # This is the URL of the MCP server we want to use. server_url = "http://localhost:8000/mcp" @@ -114,32 +109,32 @@ The example below also shows `MultiMCPTools`, which is deprecated and will be re await mcp_tools.close() - # Using MultiMCPTools, we can connect to multiple MCP servers at once, even if they use different transports. - # In this example we connect to both our example server (Streamable HTTP transport), and a different server (stdio transport). - async def run_agent_with_multimcp(message: str) -> None: + # With one MCPTools instance per server, we can connect to multiple MCP servers at once, + # even if they use different transports. In this example we connect to both our example + # server (Streamable HTTP transport) and a different server (stdio transport). + async def run_agent_with_multiple_servers(message: str) -> None: # Initialize and connect to multiple MCP servers with different transports - mcp_tools = MultiMCPTools( - commands=["npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt"], - urls=[server_url], - urls_transports=["streamable-http"], - ) - await mcp_tools.connect() + airbnb_tools = MCPTools(command="npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt") + calendar_tools = MCPTools(transport="streamable-http", url=server_url) + await airbnb_tools.connect() + await calendar_tools.connect() try: agent = Agent( model=OpenAIResponses(id="gpt-5.2"), - tools=[mcp_tools], + tools=[airbnb_tools, calendar_tools], markdown=True, ) await agent.aprint_response(input=message, stream=True, markdown=True) finally: - await mcp_tools.close() + await airbnb_tools.close() + await calendar_tools.close() if __name__ == "__main__": asyncio.run(run_agent("Do I have any birthdays this week?")) asyncio.run( - run_agent_with_multimcp( + run_agent_with_multiple_servers( "Can you check when is my mom's birthday, and if there are any AirBnb listings in SF for two people for that day?" ) ) diff --git a/tools/toolkits/database/google-bigquery.mdx b/tools/toolkits/database/google-bigquery.mdx index 21b1584b3..abd36b83c 100644 --- a/tools/toolkits/database/google-bigquery.mdx +++ b/tools/toolkits/database/google-bigquery.mdx @@ -56,6 +56,10 @@ agent.print_response("List all tables in the dataset and describe the sales tabl | `run_sql_query` | `bool` | `True` | Enable SQL query execution functionality. | | `all` | `bool` | `False` | Enables all functionality when set to True. | + +The legacy aliases `enable_list_tables`, `enable_describe_table`, and `enable_run_sql_query` are also accepted. When one is passed, it overrides the matching bare flag. + + ## Toolkit Functions | Function | Description | diff --git a/tools/toolkits/others/google-sheets.mdx b/tools/toolkits/others/google-sheets.mdx index 8a0c8583a..60dda00f6 100644 --- a/tools/toolkits/others/google-sheets.mdx +++ b/tools/toolkits/others/google-sheets.mdx @@ -85,6 +85,10 @@ agent.print_response("Please tell me about the contents of the spreadsheet") | `create_duplicate_sheet` | `bool` | `False` | Enable creating a duplicate sheet. | | `all` | `bool` | `False` | Enable all tools. | + +The legacy aliases `enable_read_sheet`, `enable_create_sheet`, `enable_update_sheet`, and `enable_create_duplicate_sheet` are also accepted. When one is passed, it overrides the matching bare flag. + + ## Toolkit Functions | Function | Description | diff --git a/tools/toolkits/search/duckduckgo.mdx b/tools/toolkits/search/duckduckgo.mdx index 290607de3..c6523db75 100644 --- a/tools/toolkits/search/duckduckgo.mdx +++ b/tools/toolkits/search/duckduckgo.mdx @@ -49,9 +49,9 @@ agent.print_response("Whats happening in France?", markdown=True) | `web_search` | Search DuckDuckGo for a query. Parameters include `query` (str) for the search query and `max_results` (int, default=5) for maximum results. Returns JSON formatted search results. | | `search_news` | Get the latest news from DuckDuckGo. Parameters include `query` (str) for the search query and `max_results` (int, default=5) for maximum results. Returns JSON formatted news results. | - -For backward compatibility, the aliases `duckduckgo_search` and `duckduckgo_news` are also available. - + +The old method aliases `duckduckgo_search` and `duckduckgo_news` were removed in Agno v3.0 — use `web_search` and `search_news`. + ## Developer Resources diff --git a/tools/toolkits/search/seltz.mdx b/tools/toolkits/search/seltz.mdx index 63e40c5a3..49b3beb0e 100644 --- a/tools/toolkits/search/seltz.mdx +++ b/tools/toolkits/search/seltz.mdx @@ -42,8 +42,7 @@ agent.print_response("Search for current AI safety reports") | `api_key` | `Optional[str]` | `None` | Seltz API key. If not provided, uses `SELTZ_API_KEY` environment variable. | | `endpoint` | `Optional[str]` | `None` | Custom Seltz gRPC endpoint. If not provided, uses SDK default. | | `insecure` | `bool` | `False` | Use an insecure gRPC channel. | -| `max_results` | `Optional[int]` | `None` | Default maximum number of results to return per search. Defaults to `10` when unset. | -| `max_documents` | `Optional[int]` | `None` | Deprecated alias for `max_results`. | +| `max_results` | `Optional[int]` | `None` | Default maximum number of results to return per search. Defaults to `10` when unset. In Agno v3.0 the old `max_documents` alias was removed; passing it raises a `TypeError`. | | `context` | `Optional[str]` | `None` | Legacy SDK context to improve search quality. Ignored by current Seltz SDK versions. | | `profile` | `Optional[str]` | `None` | Legacy SDK search profile to use for ranking. | | `show_results` | `bool` | `False` | Log search results for debugging. | @@ -54,7 +53,7 @@ agent.print_response("Search for current AI safety reports") | Function | Description | | -------- | ----------- | -| `search_seltz` | Search Seltz for a query. Returns results as JSON with document URLs and content. Accepts `query` (str), optional `max_results` (int), and optional filters: `scope`, `include_domains`, `exclude_domains`, `from_date`, and `to_date`. `max_documents` remains available as a deprecated alias for `max_results`. | +| `search_seltz` | Search Seltz for a query. Returns results as JSON with document URLs and content. Accepts `query` (str), optional `max_results` (int), and optional filters: `scope`, `include_domains`, `exclude_domains`, `from_date`, and `to_date`. The filters require `seltz>=1.2.0`; older SDKs still work for plain searches through a fallback. | ## Developer Resources diff --git a/tools/toolkits/web-scrape/brightdata.mdx b/tools/toolkits/web-scrape/brightdata.mdx index 792e30321..0070fc214 100644 --- a/tools/toolkits/web-scrape/brightdata.mdx +++ b/tools/toolkits/web-scrape/brightdata.mdx @@ -71,7 +71,7 @@ agent.print_response( | Function | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scrape_as_markdown` | Scrapes a webpage and returns content in Markdown format. Parameters: `url` (str) - URL to scrape. | -| `get_screenshot` | Captures a screenshot of a webpage and adds it as an image artifact. Parameters: `url` (str) - URL to screenshot, `output_path` (str, optional) - Unused, kept for compatibility. | +| `get_screenshot` | Captures a screenshot of a webpage and adds it as an image artifact. Parameters: `url` (str) - URL to screenshot. | | `search_engine` | Searches using Google, Bing, or Yandex and returns results in Markdown. Parameters: `query` (str), `engine` (str, default: "google"), `num_results` (int, default: 10), `language` (Optional[str]), `country_code` (Optional[str]). | | `web_data_feed` | Retrieves structured data from various sources like LinkedIn, Amazon, Instagram, etc. Parameters: `source_type` (str), `url` (str), `num_of_reviews` (Optional[int]). | From 3c90ade645e024b05ba4910e0eb729612c2569ad Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 1 Sep 2026 17:45:16 +0530 Subject: [PATCH 2/3] docs: add pages for the v3.0 tool and model integrations Nine new pages, written from tag-pinned code (v3.0.4) and registered in the nav: KnowledgeManagementTools, AtomicMail, SuperGrok OAuth for xAIResponses, FinanceTools, RampRouter, CodeMode, MiniMax video tools, Serply, and WaveSpeed. The two provider pages register in both provider trees with catalog and compatibility rows; the toolkit pages get overview cards and cross-link Notes on their sibling pages. Every version Badge was established by git ls-tree across tags; AtomicMail, Serply and WaveSpeed shipped in v3.0.2, not where the release notes place them. --- docs.json | 33 +++- models/compatibility.mdx | 2 + models/providers/gateways/ramp/overview.mdx | 98 ++++++++++ models/providers/model-index.mdx | 12 +- .../providers/native/xai/supergrok-oauth.mdx | 177 ++++++++++++++++++ tools/toolkits/local/code-mode.mdx | 114 +++++++++++ tools/toolkits/models/minimax.mdx | 101 ++++++++++ tools/toolkits/others/finance.mdx | 101 ++++++++++ tools/toolkits/others/financial-datasets.mdx | 4 + .../toolkits/others/knowledge-management.mdx | 114 +++++++++++ tools/toolkits/others/knowledge.mdx | 4 + tools/toolkits/others/wavespeed.mdx | 84 +++++++++ tools/toolkits/others/yfinance.mdx | 4 + tools/toolkits/overview.mdx | 56 ++++++ tools/toolkits/search/serply.mdx | 78 ++++++++ tools/toolkits/social/atomic-mail.mdx | 87 +++++++++ 16 files changed, 1065 insertions(+), 4 deletions(-) create mode 100644 models/providers/gateways/ramp/overview.mdx create mode 100644 models/providers/native/xai/supergrok-oauth.mdx create mode 100644 tools/toolkits/local/code-mode.mdx create mode 100644 tools/toolkits/models/minimax.mdx create mode 100644 tools/toolkits/others/finance.mdx create mode 100644 tools/toolkits/others/knowledge-management.mdx create mode 100644 tools/toolkits/others/wavespeed.mdx create mode 100644 tools/toolkits/search/serply.mdx create mode 100644 tools/toolkits/social/atomic-mail.mdx diff --git a/docs.json b/docs.json index ae54591ca..26061626a 100644 --- a/docs.json +++ b/docs.json @@ -1465,7 +1465,8 @@ "models/providers/native/xai/usage/live-search-agent-stream", "models/providers/native/xai/usage/reasoning-agent" ] - } + }, + "models/providers/native/xai/supergrok-oauth" ] }, { @@ -2022,6 +2023,16 @@ } ] }, + { + "group": "Ramp Router", + "pages": [ + "models/providers/gateways/ramp/overview", + { + "group": "Usage", + "pages": [] + } + ] + }, { "group": "Tuning Engines", "pages": [ @@ -2226,6 +2237,7 @@ "tools/toolkits/search/seltz", "tools/toolkits/search/serpapi", "tools/toolkits/search/serper", + "tools/toolkits/search/serply", "tools/toolkits/search/sofya", "tools/toolkits/search/tavily", "tools/toolkits/search/valyu", @@ -2237,6 +2249,7 @@ { "group": "Social", "pages": [ + "tools/toolkits/social/atomic-mail", "tools/toolkits/social/discord", "tools/toolkits/social/email", "tools/toolkits/social/gmail", @@ -2287,6 +2300,7 @@ "group": "Local", "pages": [ "tools/toolkits/local/calculator", + "tools/toolkits/local/code-mode", "tools/toolkits/local/coding", "tools/toolkits/local/docker", "tools/toolkits/local/file", @@ -2309,6 +2323,7 @@ "tools/toolkits/models/azure-openai", "tools/toolkits/models/gemini", "tools/toolkits/models/groq", + "tools/toolkits/models/minimax", "tools/toolkits/models/morph", "tools/toolkits/models/nebius", "tools/toolkits/models/openai" @@ -2346,6 +2361,7 @@ "tools/toolkits/others/e2b", "tools/toolkits/others/evm", "tools/toolkits/others/fal", + "tools/toolkits/others/finance", "tools/toolkits/others/financial-datasets", "tools/toolkits/others/giphy", "tools/toolkits/others/github", @@ -2357,6 +2373,7 @@ "tools/toolkits/others/google-slides", "tools/toolkits/others/jira", "tools/toolkits/others/knowledge", + "tools/toolkits/others/knowledge-management", "tools/toolkits/others/linear", "tools/toolkits/others/llms-txt", "tools/toolkits/others/lumalabs", @@ -2383,6 +2400,7 @@ "tools/toolkits/others/user-control-flow", "tools/toolkits/others/user-feedback", "tools/toolkits/others/visualization", + "tools/toolkits/others/wavespeed", "tools/toolkits/others/web-browser", "tools/toolkits/others/webtools", "tools/toolkits/others/yfinance", @@ -3400,7 +3418,8 @@ "models/providers/native/xai/usage/live-search-agent-stream", "models/providers/native/xai/usage/reasoning-agent" ] - } + }, + "models/providers/native/xai/supergrok-oauth" ] }, { @@ -3942,6 +3961,16 @@ } ] }, + { + "group": "Ramp Router", + "pages": [ + "models/providers/gateways/ramp/overview", + { + "group": "Usage", + "pages": [] + } + ] + }, { "group": "Tuning Engines", "pages": [ diff --git a/models/compatibility.mdx b/models/compatibility.mdx index 2df8efd9d..81c47768c 100644 --- a/models/compatibility.mdx +++ b/models/compatibility.mdx @@ -75,6 +75,7 @@ Each checkmark records a media path implemented by the adapter and corroborated | `OpenRouterResponses` | | | | | | | `Perplexity` | | | | | | | `Portkey` | | | | | | +| `RampRouter` | | | | | | | `Requesty` | | | | | | | `Sambanova` | | | | | | | `Siliconflow` | | | | | | @@ -84,6 +85,7 @@ Each checkmark records a media path implemented by the adapter and corroborated | `VLLM` | | | | | | | `Claude` (Vertex AI) | ✅ | | | | ✅ | | `xAI` | ✅ | | | | | +| `xAIResponses` | | | | | | | `MiMo` | | | | | | ## Developer Resources diff --git a/models/providers/gateways/ramp/overview.mdx b/models/providers/gateways/ramp/overview.mdx new file mode 100644 index 000000000..4359e2fe9 --- /dev/null +++ b/models/providers/gateways/ramp/overview.mdx @@ -0,0 +1,98 @@ +--- +title: Ramp Router +sidebarTitle: Overview +description: Use Ramp Router's model-routing API with Agno agents. +--- + + + v3.0.0 + + +[Ramp Router](https://router.com) routes requests across model providers behind one OpenAI-compatible Responses endpoint. `RampRouter` connects Agno agents to it. + +Model ids are account-scoped: Router's `GET /v1/models` lists what your key can use. Router's rate limits, per-model service tiers, timeout maxima, and spend controls are set by Router and vary by model — see Router's [errors and limits](https://docs.router.com/api/errors-and-limits) and [control spend](https://docs.router.com/guides/control-spend) pages rather than this one. + +## Installation + +```bash +uv pip install -U "agno[openai]" +``` + +`RampRouter` uses the OpenAI Python SDK, which the `agno[openai]` extra provides. + +## Authentication + +Set your `RAMP_ROUTER_API_KEY` environment variable. Get your key from the Router dashboard. + + + +```bash Mac +export RAMP_ROUTER_API_KEY=*** +``` + +```bash Windows +setx RAMP_ROUTER_API_KEY *** +``` + + + +## Example + +Use `RampRouter` with your `Agent`: + + + +```python agent.py +from agno.agent import Agent +from agno.models.ramp import RampRouter + +agent = Agent( + model=RampRouter(id="gpt-5.6-luna"), + markdown=True, +) + +agent.print_response("Share a 2 sentence horror story.") +``` + + + +The model string `"ramp:gpt-5.6-luna"` resolves to the same class. The spelling `"ramprouter:"` also resolves, but `"ramp:"` is the registered form. + +## Server-Side Fallback + +`models=[...]` is Router's server-side fallback: one to fifteen Router catalog ids (for example `"openai:gpt-5-nano"`, optionally `":flex"`-suffixed), tried in order on Router's side. When `models` is set, Agno omits the single `id` from the request. This is distinct from Agno's client-side [fallback models](/models/fallback-models), which retry against a different provider from your process. + +```python +from agno.agent import Agent +from agno.models.ramp import RampRouter + +agent = Agent( + model=RampRouter(models=["openai:gpt-5-nano", "anthropic:claude-haiku-4-5"]), + markdown=True, +) +``` + +`allow_flex_tier` is forwarded to Router with the request; Router accepts `False` on any model and rejects `True` with a 400 on models without Flex capacity. See Router's [request fields](https://docs.router.com/api/request-fields) for the tier semantics. + +## Behavior Notes + +- Background mode is not supported: constructing `RampRouter(background=True)` raises `ValueError`. +- Token counting is local. `count_tokens` and `acount_tokens` estimate from the messages in your process instead of calling the API. +- A generation that runs out of `max_output_tokens` ends as an incomplete response; Agno reads the usage from it and logs that Router stopped the response early. + +## Parameters + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `id` | `str` | `"gpt-5.6-luna"` | The id of the model to route to. Account-scoped; Router's `GET /v1/models` is the authoritative list | +| `name` | `str` | `"RampRouter"` | The name of the model | +| `provider` | `str` | `"RampRouter"` | The provider of the model | +| `api_key` | `Optional[str]` | `None` | Router API key (defaults to the `RAMP_ROUTER_API_KEY` env var) | +| `base_url` | `str` | `"https://api.router.com/v1"` | The base URL for the Router API | +| `store` | `Optional[bool]` | `None` | Whether to store the response on the provider side. When unset, Router applies its own default | +| `models` | `Optional[List[str]]` | `None` | Server-side fallback list of Router catalog ids, tried in order. Mutually exclusive with `id` in the request | +| `allow_flex_tier` | `Optional[bool]` | `None` | Forwarded to Router; see Router's [request fields](https://docs.router.com/api/request-fields) | +| `provider_timeout` | `Optional[float]` | `None` | Router-side per-provider timeout in seconds, forwarded in the request body. Maxima are set per gateway by Router | +| `timeout_before_headers` | `Optional[float]` | `None` | Router-side timeout in seconds until response headers arrive, forwarded in the request body. Maxima are set per gateway by Router | + +`RampRouter` extends [OpenResponses](/reference/models/open-responses) and accepts all of its parameters. diff --git a/models/providers/model-index.mdx b/models/providers/model-index.mdx index ddab95ead..89e7aae01 100644 --- a/models/providers/model-index.mdx +++ b/models/providers/model-index.mdx @@ -385,6 +385,14 @@ Browse the provider guides available in this documentation. Capabilities vary by > Route requests through the Portkey AI Gateway. + + Route requests across model providers with Ramp Router. + + v3.0.0 + + +**xAIResponses** runs Grok models on xAI's Responses API with two credential modes: an API key (`XAI_API_KEY`), or a SuperGrok subscription sign-in through xAI's device-code flow. This page covers the sign-in path. + + +SuperGrok sign-in works only on `xAIResponses`. The `xAI` chat class is unchanged and takes an API key only. + + +See all xAI models [here](https://docs.x.ai/docs/models). + +- We recommend setting `id="grok-4.3"` explicitly. The class default `grok-4-1-fast-non-reasoning-latest` is an alias xAI has retired and redirects to Grok 4.3. + +## Installation + +```bash +uv pip install -U "agno[openai,sqlite]" cryptography +``` + +SuperGrok sign-in needs `openai>=1.106.0` — the first release whose client accepts a callable API key — and the `agno[openai]` extra pins it. It also needs the `cryptography` package, which is in no Agno extra: tokens are stored encrypted with Fernet. If `cryptography` is missing, nothing fails at construction, but the first successful login — and any later token refresh or load — raises `ImportError`, and the sign-in does not persist across restarts. The `agno[sqlite]` extra covers `sqlalchemy` for the examples' SQLite token store. + +## Authentication + +Set `XAI_TOKEN_ENCRYPTION_KEY` to a Fernet key. Generate one: + +```bash +python -c "from agno.utils.encryption import generate_encryption_key; print(generate_encryption_key())" +``` + + + +```bash Mac +export XAI_TOKEN_ENCRYPTION_KEY=*** +``` + +```bash Windows +setx XAI_TOKEN_ENCRYPTION_KEY *** +``` + + + +Token encryption is required by default. Without the key, a completed sign-in is kept in process memory but not saved — a restart signs you out, with a warning in the logs. `XAITokenManager(encrypt_tokens=False)` stores the token unencrypted and needs no key; use it for local development only. + +### Entitlement + +The device-code flow requests the OAuth scopes `openid profile email offline_access grok-cli:access api:access` from `auth.x.ai`, then calls the same `https://api.x.ai/v1` endpoints an API key would. Whether your SuperGrok subscription includes API access is decided by xAI, not by Agno — check your plan at [x.ai](https://x.ai). If it does not, the first request fails with a 403 that Agno rewrites as: + +```text +xAI rejected this request (403). When signed in with SuperGrok this usually +means the subscription tier does not include this model or API access, the +subscription is inactive, or its quota is exhausted — note X Premium does not +include xAI API access. Retrying or re-logging-in will not help. To use +pay-per-token access instead, set XAI_API_KEY. +``` + +followed by xAI's own error message. + +## Example + +In a terminal, drive the device flow directly: show the URL and code, wait for the browser approval, and run the agent. + + + +```python oauth_device_login.py +import time + +from agno.agent import Agent +from agno.db.sqlite import SqliteDb +from agno.models.xai import xAIResponses +from agno.models.xai.oauth import XAITokenManager + +# SqliteDb is for local development only; use PostgresDb in production +db = SqliteDb(db_file="tmp/xai_oauth.db") +token_manager = XAITokenManager(db=db) + +info = token_manager.start_device_login() +print("Open this URL and approve the sign-in:") +print(info.verification_uri_complete) +print("Code: " + info.user_code) +token_manager.poll_for_token( + info.device_code, info.interval, time.time() + info.expires_in +) + +agent = Agent(model=xAIResponses(id="grok-4.3", token_manager=token_manager), markdown=True) +agent.print_response("Share a 2 sentence horror story") +``` + + + +The model string `"xai-responses:grok-4.3"` resolves to the same class. The string form constructs the model with its id only, so attach the session afterwards: `agent.model.token_manager = token_manager`. + +## Signing In from Chat + +For chatbots and web UIs, where a terminal device flow cannot run, the `XAIAuth` toolkit wraps the same manager as two agent tools: `sign_in_with_supergrok` hands back the approval link and code, and `check_supergrok_login` completes the login on a later turn. The in-flight login is stored in the database, so whichever replica handles the user's next turn can finish it. AgentOS ships no sign-in route of its own — `XAIAuth` is the only sign-in path there. + +An agent cannot sign in to the model it is running on: reaching the sign-in tool takes an inference call, and that call is the one with no credential yet. Put `XAIAuth` on an agent running a different model: + +```python +from agno.agent import Agent +from agno.db.sqlite import SqliteDb +from agno.models.openai import OpenAIResponses +from agno.models.xai import xAIResponses +from agno.models.xai.oauth import XAITokenManager +from agno.tools.xai_auth import XAIAuth + +db = SqliteDb(db_file="tmp/xai_oauth.db") +token_manager = XAITokenManager(db=db) + +signin_agent = Agent( + model=OpenAIResponses(id="gpt-5.5"), + tools=[XAIAuth(token_manager=token_manager)], + db=db, + # The second turn refers back to the link handed out on the first + add_history_to_context=True, + markdown=True, +) + +grok_agent = Agent(model=xAIResponses(id="grok-4.3", token_manager=token_manager), markdown=True) +``` + +## Token Storage + +Where the signed-in token lives, in order of preference: + +- **Database** — pass `db=` to `XAITokenManager`. Auth-token storage is implemented by the Postgres and SQLite adapters, sync and async; the table (`agno_auth_tokens` by default) is created on demand, with no migration to run. Rows are keyed by provider (`"xai"`), user id, and service (`"supergrok"`), and the token data inside the row is encrypted. Any other adapter logs a warning and falls back to the file store. +- **File** — with no database, the token lands in `xai_token.json` relative to the process working directory (override with `token_path`), written with file mode 0600. The file holds one session: the shared deployment slot. +- **Memory** — with encryption required but no key configured, the token stays in process memory only. + +A sync run (`agent.run`) with an async DB adapter cannot await the adapter: it logs a warning and falls back to the file store. Async runs (`agent.arun`) use the async adapters natively. + +Access tokens are refreshed automatically shortly before expiry. A refresh that fails with `invalid_grant` deletes the stored token and raises a `ModelAuthenticationError` telling the user to sign in again or set `XAI_API_KEY`. + +## Multiple Users + +Per-user sign-in keys each token to the run's `user_id`: a user who signed in through `XAIAuth` gets their own stored session, and requests for that user are sent with their token. Per-user tokens require a database — the file store holds only the deployment slot, and refuses per-user writes with a warning. + +Requests for an identified user with no stored session fall back to the deployment slot. Set `require_user_token=True` on `xAIResponses` to refuse that fallback: requests for a user who has not signed in then fail with a `ModelAuthenticationError` instead of silently spending the shared subscription. + +## Signing Out + +`sign_out(user_id)` on the manager deletes the stored token. It does not call a revocation endpoint — the grant lives on server-side until it expires or is revoked from the xAI account page. + +## Parameters + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `id` | `str` | `"grok-4-1-fast-non-reasoning-latest"` | The id of the xAI model to use | +| `name` | `str` | `"xAIResponses"` | The name of the model | +| `provider` | `str` | `"xAI"` | The provider of the model | +| `api_key` | `Optional[str]` | `None` | xAI API key. When set, it wins over every sign-in field; when unset and no sign-in field is configured, falls back to the `XAI_API_KEY` env var | +| `base_url` | `str` | `"https://api.x.ai/v1"` | The base URL for the xAI API, in both credential modes | +| `store` | `Optional[bool]` | `False` | Whether to store the response on the provider side | +| `token_provider` | `Optional[Callable[[], str]]` | `None` | Callable returning a bearer token, for custom token sources | +| `async_token_provider` | `Optional[Callable[[], Awaitable[str]]]` | `None` | Async variant of `token_provider`. Cannot serve the sync client | +| `token_manager` | `Optional[XAITokenManager]` | `None` | Manages the SuperGrok device login, token refresh, and storage | +| `require_user_token` | `bool` | `False` | Refuse the deployment-slot fallback for identified users. Requires `token_manager` | + +### XAITokenManager + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `db` | `Optional[Any]` | `None` | Database for token storage. Postgres and SQLite adapters, sync and async | +| `token_path` | `Optional[str]` | `None` | Token file path. Defaults to `xai_token.json` in the process working directory | +| `encryption_key` | `Optional[str]` | `None` | Fernet key for token encryption. Defaults to the `XAI_TOKEN_ENCRYPTION_KEY` env var | +| `encrypt_tokens` | `bool` | `True` | Require encryption. Without a key the token is not persisted; `False` stores plaintext (local development only) | +| `http_client` | `Optional[httpx.Client]` | `None` | Custom httpx client for the OAuth endpoints | +| `async_http_client` | `Optional[httpx.AsyncClient]` | `None` | Custom async httpx client for the OAuth endpoints | +| `timeout` | `float` | `30.0` | Timeout in seconds for OAuth requests | + +`xAIResponses` extends [OpenResponses](/reference/models/open-responses) and accepts all of its parameters. For the API-key mode and the `xAI` chat class, see the [xAI overview](/models/providers/native/xai/overview). diff --git a/tools/toolkits/local/code-mode.mdx b/tools/toolkits/local/code-mode.mdx new file mode 100644 index 000000000..be1737765 --- /dev/null +++ b/tools/toolkits/local/code-mode.mdx @@ -0,0 +1,114 @@ +--- +title: CodeMode +description: "CodeMode gives an agent one persistent IPython kernel to write Python in, with its tools bound as awaitable handles." +--- + + + v3.0.0 + + +**CodeMode** replaces a wide tool schema with one programmable environment. The model writes Python that runs in an IPython kernel persisting for the session, so variables, imports, and helper functions survive across turns. Toolkits passed to it are not listed in the model's schema: they are bound inside the kernel as awaitable handles the code can call, composing tools with variables, loops, and helpers instead of round-tripping each call through the transcript. + + +CodeMode is not a sandbox. Cells run arbitrary Python — and, by default, `%%bash` shell commands — with the host process's permissions, and restoring a persisted snapshot is itself code execution. `allow_shell=False` removes the shell magic but is a footgun reducer, not a security boundary. For untrusted use, run the agent inside a real sandbox (container or VM). + + +## Prerequisites + +CodeMode requires Python 3.10 or newer. The `agno[code]` extra provides `ipykernel`, `jupyter_client`, and `dill`; the example also uses the `openai` library: + +```shell +uv pip install -U "agno[code]" openai +``` + +## Example + +```python cookbook/code/01_basics/basic.py +from agno.agent import Agent +from agno.models.openai import OpenAIResponses +from agno.tools.code import CodeMode + +code = CodeMode() + +agent = Agent( + model=OpenAIResponses(id="gpt-5.5"), + tools=[code], + instructions="Use the code environment to compute answers. Print summaries, not raw data.", + markdown=True, +) + +try: + agent.print_response( + "Build a list of the first 200 Fibonacci numbers in the code environment, " + "keep it in a variable, and tell me only how many of them are even and " + "how many digits the largest one has.", + session_id="code-mode-basic", + ) +finally: + code.shutdown() +``` + +## How a Cell Runs + +The model sees two tools by default: `execute` and, unless `allow_restart=False`, `restart`. The first `execute` in a session starts an IPython kernel subprocess keyed on the run's session id — the id comes from the framework, never from a model argument — and the kernel is reused across runs in the same process until it has been idle for `idle_ttl` seconds. + +Toolkits and functions passed via `tools=` become awaitable handles inside the kernel: the handle name is the toolkit name with a trailing `_tools` stripped, and each function is an async stub the code can `await`. The host runs the real tool call, so `tool_hooks`, `pre_hook`/`post_hook`, and result caching still apply — and a whole cell counts as one call toward the agent's `tool_call_limit`. Tools that pause a run (`requires_confirmation`, `external_execution`, `requires_user_input`) are bound as stubs that refuse with a fixed message, because a cell cannot pause the run. The generated instructions tell the model which handles exist, that state persists, and the `%%bash` rules. + +Cell output returns stdout, a stderr block, the `Out[n]:` repr, or a traceback; each stream is capped at `max_output_chars` with the truncated streams named, and PNG display output is promoted to image artifacts (at most `max_images_per_cell`, each at most `max_image_bytes`). + +Failure modes: + +- An exception in the cell returns its traceback to the model as an error result. +- A cell over `timeout` seconds is interrupted; if the kernel does not respond to the interrupt, the cell returns as aborted and the next cell must wait for the kernel to clear within `busy_wait` seconds — otherwise the model is told the environment is busy and to retry or restart. With `on_busy_kernel="restart"`, CodeMode instead restarts the kernel and re-runs the cell once. +- A kernel that dies mid-cell reports the death; a fresh kernel starts on the next `execute`, with previous state gone. +- A bridged tool result over `max_result_bytes` raises a `ResultTooLarge` error inside the cell, telling the model to enable result offloading or write large payloads to the file system — unless the agent has result offloading enabled, in which case the result is offloaded and the cell receives an envelope id. + +## Persistence + +With `fs=` set to an AgentFS `FileSystem` and `snapshot=True` (the default), every successful cell schedules a debounced per-variable snapshot, and a new kernel for a known session restores it before binding tools — so kernel state survives process restarts. Unpicklable or oversized variables are skipped and named in the restore notice the model sees. The snapshot caps are lowered to the FileSystem's own per-file and per-namespace limits when those are smaller, with a warning naming the reduction. + +A session is owned by the `user_id` of the run that created it; a later run with a different `user_id` is refused and gets no kernel. The run-end `close()` flushes pending snapshots but keeps kernels alive; call `shutdown()` to snapshot and kill them. + +## Teams + +A team leader and members share the team session id, so members sharing one CodeMode instance share one kernel namespace — and concurrent cells contend for it under the busy-kernel rules above. Share one instance when members should build on each other's variables; give members separate instances when their state must stay isolated. + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `tools` | `Optional[Sequence[Union[Toolkit, Callable, Function]]]` | `None` | Toolkits and functions to bind inside the kernel as awaitable handles. | +| `fs` | `Optional[FileSystem]` | `None` | AgentFS file system for snapshots. Without it, `snapshot` is inert. | +| `snapshot` | `bool` | `True` | Persist kernel variables to `fs` after successful cells and restore them for known sessions. | +| `snapshot_debounce` | `float` | `1.5` | Seconds to debounce snapshot writes after a cell. | +| `max_variable_bytes` | `int` | `2000000` | Per-variable snapshot cap. Lowered to the FileSystem's per-file limit when that is smaller. | +| `max_snapshot_bytes` | `int` | `64000000` | Per-snapshot cap. Lowered to the FileSystem's per-namespace limit when that is smaller. | +| `max_output_chars` | `int` | `65536` | Cap per output stream (stdout, stderr, result), truncating with head and tail kept. | +| `max_result_bytes` | `int` | `1000000` | Cap on a bridged tool result entering the kernel. Over it, the cell gets a `ResultTooLarge` error unless result offloading is enabled. | +| `allow_restart` | `bool` | `True` | Register the restart tool. | +| `allow_shell` | `bool` | `True` | Allow `%%bash` cells. `False` removes the magic; it is not a security boundary. | +| `on_busy_kernel` | `Literal["wait", "restart"]` | `"wait"` | What to do when a cell arrives while the kernel is busy: report busy after `busy_wait`, or restart and re-run once. | +| `busy_wait` | `float` | `5.0` | Seconds to wait for a busy kernel to clear. | +| `idle_ttl` | `int` | `1800` | Seconds of idleness before a kernel is evicted, snapshot flushed first. | +| `timeout` | `Optional[int]` | `300` | Per-cell timeout in seconds. `None` waits indefinitely. | +| `python` | `Optional[str]` | `None` | Python executable for the kernel. Defaults to the running interpreter. | +| `cwd` | `Optional[str]` | `None` | Working directory for the kernel subprocess. | +| `env` | `Optional[Dict[str, str]]` | `None` | Environment variables laid over the process environment for the kernel subprocess. | +| `startup_code` | `Optional[str]` | `None` | Code run once when a kernel starts. | +| `max_images_per_cell` | `int` | `8` | Cap on PNG images promoted from one cell's display output. | +| `max_image_bytes` | `int` | `5000000` | Cap per promoted image. | +| `max_kernels` | `Optional[int]` | `None` | Cap on live kernels; idle sessions are evicted least-recently-used first. `None` keeps every session until `idle_ttl`. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `execute` | Run a Python cell (or a `%%bash` cell when enabled) in the session's kernel. Parameters: `code` (str). Returns the cell output, with images attached as artifacts. | +| `restart` | Discard the kernel and all its state, including the persisted snapshot, and start fresh. Registered unless `allow_restart=False`. | + +Both tools have async variants registered under the same names. A developer surface exists alongside the model-facing tools — `run`, `variables`, `value`, and `shutdown`, each with an `a`-prefixed async twin — for driving or inspecting a session from your own code. + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/code/code_mode.py) +- [Cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/code) diff --git a/tools/toolkits/models/minimax.mdx b/tools/toolkits/models/minimax.mdx new file mode 100644 index 000000000..be0a1f272 --- /dev/null +++ b/tools/toolkits/models/minimax.mdx @@ -0,0 +1,101 @@ +--- +title: MiniMax +description: "MiniMaxTools generate videos from text prompts through the MiniMax API." +--- + + + v3.0.0 + + +**MiniMaxTools** enable an Agent to generate videos from text prompts with [MiniMax](https://www.minimax.io/)'s video generation API. Generation is asynchronous on MiniMax's side: the tool submits the job, polls until it finishes, and returns the video as a remote URL. + +## Prerequisites + +No extra package is required beyond `agno` — the toolkit uses `httpx`, an Agno core dependency. The example also uses the `openai` library: + +```shell +uv pip install -U agno openai +``` + +Set the `MINIMAX_API_KEY` environment variable. Get your key from [MiniMax's platform](https://platform.minimax.io/). + +```shell +export MINIMAX_API_KEY=*** +``` + +Without the key, construction logs an error and every call returns "Please set the MINIMAX_API_KEY" as the tool result. + +## Example + +```python cookbook/91_tools/minimax_tools.py +from agno.agent import Agent +from agno.models.openai import OpenAIResponses +from agno.tools.minimax import MiniMaxTools + +minimax_agent = Agent( + name="MiniMax Video Generator Agent", + model=OpenAIResponses(id="gpt-5.6-luna"), + tools=[ + MiniMaxTools( + # Use region="cn_zh" for the mainland China endpoint. + region="global_en", + model="MiniMax-H3", + ) + ], + description="You are an AI agent that can generate videos using the MiniMax API.", + instructions=[ + "When the user asks you to create a video, use the `generate_video` tool.", + "Duration is given in whole seconds, from 4 through 15.", + "Return the URL as raw to the user.", + ], + markdown=True, +) + +minimax_agent.print_response("Generate a video of a paper boat crossing a moonlit lake") +``` + +## How Generation Runs + +`generate_video` submits the prompt, reads the task id from the response, and polls the task status every `poll_interval` seconds until MiniMax reports it succeeded, failed, or cancelled — or until `max_wait_time` is reached. The tool call blocks for the whole wait; each poll request times out at `timeout` seconds, clipped to the remaining budget. + +On success, the tool returns "Video generated successfully" with the video attached as an `agno.media.Video` artifact carrying a remote URL (`video/mp4`). The bytes are never downloaded — how long MiniMax serves the URL is MiniMax's side; see [MiniMax's platform docs](https://platform.minimax.io/). + +The tool never raises. Every failure comes back as the tool result's text: a missing task id or video URL, the failure message on a failed or cancelled task, "Video generation timed out after `max_wait_time` seconds", or "Error generating video: ..." for HTTP errors. + +## Custom Endpoints + +`region` selects the default endpoint: `"global_en"` uses `https://api.minimax.io/v2/video_generation` and `"cn_zh"` uses `https://api.minimaxi.com/v2/video_generation`. Any other value raises a `ValueError` at construction — also when `base_url` is set. + +`base_url`, when set, overrides the region default and must be the full video-generation endpoint. The task-status endpoint is not configurable separately: it is derived by replacing `/v2/video_generation` with `/v2/query/video_generation` in `base_url`, with the task id appended. A trailing slash is stripped. + + +A `base_url` without the `/v2/video_generation` path breaks polling: the submit request goes to the URL as-is and the status poll goes to `/`, failing at request time as an "Error generating video" tool result. Nothing fails at construction. + + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `api_key` | `Optional[str]` | `None` | MiniMax API key. If not provided, uses the `MINIMAX_API_KEY` env variable. | +| `base_url` | `Optional[str]` | `None` | Full video-generation endpoint. Overrides `region`. See [Custom Endpoints](#custom-endpoints). | +| `region` | `str` | `"global_en"` | Endpoint region, `"global_en"` or `"cn_zh"`. An invalid value raises a `ValueError`. | +| `model` | `str` | `"MiniMax-H3"` | MiniMax video model id. See [MiniMax's platform docs](https://platform.minimax.io/) for available models. | +| `poll_interval` | `float` | `5` | Seconds between task-status polls. | +| `max_wait_time` | `float` | `600` | Wall-clock cap in seconds on one generation, submit to finish. | +| `timeout` | `int` | `30` | Per-request HTTP timeout in seconds. | +| `enable_generate_video` | `bool` | `True` | Enable the generate_video function. | +| `all` | `bool` | `False` | Enable all functions. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `generate_video` | Generate a video from a text prompt and return it as a remote-URL video artifact. Parameters: `prompt` (str), `resolution` (str, default="2K"), `duration` (int, seconds, default=5), `ratio` (str, default="16:9"). The toolkit validates none of these values — MiniMax's API is authoritative for the supported ranges. | + +The function has an async variant registered under the same name, used automatically with `arun` and `aprint_response`. + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/minimax.py) +- [Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/minimax_tools.py) +- [MiniMax Platform Docs](https://platform.minimax.io/) diff --git a/tools/toolkits/others/finance.mdx b/tools/toolkits/others/finance.mdx new file mode 100644 index 000000000..23d923df2 --- /dev/null +++ b/tools/toolkits/others/finance.mdx @@ -0,0 +1,101 @@ +--- +title: Finance +description: "FinanceTools give an agent one set of finance tools with swappable market-data providers." +--- + + + v3.0.0 + + +**FinanceTools** provide one finance toolkit with swappable data providers: the same eleven tool names, parameters, and JSON response shape, whatever supplies the data. The default provider is Yahoo Finance (via the `yfinance` package); financialdatasets.ai is built in, and custom providers can be registered. Agent code does not change when the data source does. + +Agno ships three finance toolkits, coexisting by design. `FinanceTools` fixes the tool names while the provider is swappable; [YFinanceTools](/tools/toolkits/others/yfinance) and [FinancialDatasetsTools](/tools/toolkits/others/financial-datasets) each expose one data source directly, with their own tool names. The older two are not deprecated. + +## Prerequisites + +The default provider needs the `yfinance` package; the example also uses `openai`: + +```shell +uv pip install -U yfinance openai +``` + +The financialdatasets.ai provider needs no extra package — it uses `httpx`, an Agno core dependency — but requires an API key: + +```shell +export FINANCIAL_DATASETS_API_KEY=*** +``` + +## Example + +```python cookbook/91_tools/finance/01_market_brief.py +from agno.agent import Agent +from agno.models.openai import OpenAIResponses +from agno.tools.finance import FinanceTools + +agent = Agent( + name="Finance Agent", + model=OpenAIResponses(id="gpt-5.6"), + tools=[FinanceTools()], + instructions="Lead with the answer, then show the evidence.", + markdown=True, +) + +agent.print_response("Give me a market brief on NVIDIA", stream=True) +``` + +## Provider Selection + +`provider` accepts a `FinanceProvider` instance, a registered provider id (`"yfinance"`, `"financial_datasets"`, or one you added with `register_provider`), or `None`. With `None` (the default), FinanceTools uses Yahoo Finance if the `yfinance` package is importable, otherwise financialdatasets.ai if `FINANCIAL_DATASETS_API_KEY` is set, and otherwise raises an `ImportError` at construction telling you to install `yfinance` or set the key. An unknown id raises a `ValueError` listing the registered providers. + +Each provider declares the tools it serves, and FinanceTools registers only those: + +- **Yahoo Finance** (`"yfinance"`) serves all eleven tools. No API key is needed. +- **Financial Datasets** (`"financial_datasets"`) serves nine — it has no `search_symbols` or `get_analyst_recommendations`, and the agent never sees them. Requests carry the `FINANCIAL_DATASETS_API_KEY` as an `X-API-KEY` header; see [financialdatasets.ai](https://www.financialdatasets.ai) for plans and rate limits. + +To add a provider, subclass `FinanceProvider`, declare its `capabilities`, and call `register_provider` — the [custom provider cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/finance/06_custom_provider.py) shows the shape. + +At call time, provider failures are returned to the agent as JSON `{"error": ...}` envelopes, never raised. + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `provider` | `Union[FinanceProvider, str, None]` | `None` | Data provider: an instance, a registered id, or `None` for automatic selection. See [Provider Selection](#provider-selection). | +| `search_symbols` | `bool` | `True` | Register the search_symbols tool. | +| `quote` | `bool` | `True` | Register the get_quote tool. | +| `price_history` | `bool` | `True` | Register the get_price_history tool. | +| `company_profile` | `bool` | `True` | Register the get_company_profile tool. | +| `key_metrics` | `bool` | `True` | Register the get_key_metrics tool. | +| `news` | `bool` | `True` | Register the get_news tool. | +| `analyst_recommendations` | `bool` | `True` | Register the get_analyst_recommendations tool. | +| `financials` | `bool` | `False` | Register the get_financials tool. | +| `insider_trades` | `bool` | `False` | Register the get_insider_trades tool. | +| `earnings` | `bool` | `False` | Register the get_earnings tool. | +| `sec_filings` | `bool` | `False` | Register the get_sec_filings tool. | +| `all` | `bool` | `False` | Register all tools the provider supports. | +| `instructions` | `Optional[str]` | `None` | Custom instructions. When unset, instructions are generated from the tools that actually registered. | +| `add_instructions` | `bool` | `True` | Whether to add the instructions to the agent's context. | +| `timeout` | `Optional[float]` | `None` | Per-request timeout in seconds, applied only when FinanceTools builds the provider itself (from an id or `None`); it is ignored, with a warning, when you pass a provider instance. `None` means no timeout for Yahoo Finance but 30 seconds for Financial Datasets. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `search_symbols` | Search for ticker symbols. Parameters: `query` (str), `limit` (int, default=5, capped at 25). | +| `get_quote` | Get the current quote for a symbol. Parameters: `symbol` (str). | +| `get_price_history` | Get price history. Parameters: `symbol` (str), `period` (str, default="1mo", one of 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, ytd, max), `interval` (str, default="1d", one of 1d, 1wk, 1mo). | +| `get_company_profile` | Get the company profile for a symbol. Parameters: `symbol` (str). | +| `get_key_metrics` | Get key financial metrics for a symbol. Parameters: `symbol` (str). | +| `get_financials` | Get financial statements. Parameters: `symbol` (str), `statement` (str, default="income", one of income, balance_sheet, cash_flow), `period` (str, default="annual", one of annual, quarterly, ttm), `limit` (int, default=4, capped at 20). | +| `get_news` | Get recent news for a symbol. Parameters: `symbol` (str), `limit` (int, default=10, capped at 50). | +| `get_analyst_recommendations` | Get analyst recommendations for a symbol. Parameters: `symbol` (str). | +| `get_insider_trades` | Get insider trades. Parameters: `symbol` (str), `limit` (int, default=20, capped at 100). | +| `get_earnings` | Get earnings history. Parameters: `symbol` (str), `limit` (int, default=8, capped at 40). | +| `get_sec_filings` | Get SEC filings. Parameters: `symbol` (str), `form_type` (Optional[str]), `limit` (int, default=10, capped at 100). | + +Every tool returns JSON carrying a `provider` field, and each has an async variant registered under the same name, used automatically with `arun` and `aprint_response`. Invalid arguments are returned as JSON errors before any provider call. + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/finance/toolkit.py) +- [Cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/91_tools/finance) diff --git a/tools/toolkits/others/financial-datasets.mdx b/tools/toolkits/others/financial-datasets.mdx index 7e937b3ff..6a07e0899 100644 --- a/tools/toolkits/others/financial-datasets.mdx +++ b/tools/toolkits/others/financial-datasets.mdx @@ -5,6 +5,10 @@ description: FinancialDatasetsTools give an Agent access to stock prices, financ **FinancialDatasetsTools** provide a comprehensive API for retrieving and analyzing diverse financial datasets, including stock prices, financial statements, company information, SEC filings, and cryptocurrency data from multiple providers. + +For one finance toolkit with swappable data providers — financialdatasets.ai included — see [Finance](/tools/toolkits/others/finance). + + ## Prerequisites The toolkit requires a Financial Datasets API key that can be obtained by creating an account at [financialdatasets.ai](https://financialdatasets.ai). diff --git a/tools/toolkits/others/knowledge-management.mdx b/tools/toolkits/others/knowledge-management.mdx new file mode 100644 index 000000000..80e287d11 --- /dev/null +++ b/tools/toolkits/others/knowledge-management.mdx @@ -0,0 +1,114 @@ +--- +title: Knowledge Management +description: "KnowledgeManagementTools enable an operator agent to ingest, inspect, and remove knowledge base content." +--- + + + v3.0.4 + + +**KnowledgeManagementTools** enable a builder or operator agent to load content into a knowledge base, inspect what is loaded, and remove it. This is the write side of knowledge: end-user-facing agents get search — give them [Knowledge Tools](/tools/toolkits/others/knowledge) — while this toolkit goes to the agent that curates the base. + +The knowledge base must have a `contents_db`: every tool here reads or writes content rows, and construction raises a `ValueError` without one. + +## Prerequisites + +The following example requires the `agno`, `openai`, and `qdrant-client` libraries, and `sqlalchemy` for the SQLite contents database (`agno[sqlite]`). It connects to Qdrant on `localhost:6333`. + +```shell +uv pip install -U "agno[sqlite]" openai qdrant-client +docker run -d --name qdrant -p 6333:6333 qdrant/qdrant:latest +``` + +Set your OpenAI API key: + +```shell +export OPENAI_API_KEY=*** +``` + +## Example + +The following operator agent loads a website into the knowledge base and reports what is loaded: + +```python cookbook/91_tools/knowledge_management_tools.py +import asyncio + +from agno.agent import Agent +from agno.db.sqlite import SqliteDb +from agno.knowledge.embedder.openai import OpenAIEmbedder +from agno.knowledge.knowledge import Knowledge +from agno.models.openai import OpenAIResponses +from agno.tools.knowledge import KnowledgeManagementTools +from agno.vectordb.qdrant import Qdrant + +knowledge = Knowledge( + name="Product Docs", + contents_db=SqliteDb(db_file="tmp/knowledge_contents.db"), + vector_db=Qdrant( + collection="product-docs", + url="http://localhost:6333", + embedder=OpenAIEmbedder(id="text-embedding-3-small"), + ), +) + +operator = Agent( + name="Knowledge Operator", + model=OpenAIResponses(id="gpt-5.6-luna"), + tools=[KnowledgeManagementTools(knowledge=knowledge, max_pages=25)], + markdown=True, +) + + +async def main() -> None: + await operator.aprint_response("Load https://docs.agno.com into the knowledge base.") + await operator.aprint_response("What do we have loaded now?") + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Content Ownership + +`scope` decides who can read what the operator loads. With `scope="shared"` (the default), ingested rows are readable by every agent on the knowledge base. With `scope="user"`, rows belong to the run's `user_id` — and a run without a `user_id` gets an error back instead of silently writing to the shared bucket, where the content would be readable and deletable by everyone. + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `knowledge` | `Knowledge` | - | Knowledge base to manage (required). Must have a `contents_db`; construction raises a `ValueError` without one. | +| `scope` | `Literal["shared", "user"]` | `"shared"` | Ownership of ingested rows. See [Content Ownership](#content-ownership). | +| `max_pages` | `int` | `50` | Default page cap per site ingest. Clamped between 1 and 500. | +| `page_fetcher` | `Optional[Any]` | `None` | Custom page fetcher. The default resolves the Parallel fetcher when available, and the built-in fetcher otherwise. | +| `ingest_url` | `bool` | `True` | Register the `ingest_url` tool. | +| `ingest_path` | `bool` | `False` | Register the `ingest_path` tool. Off by default — see the warning below. | +| `ingest_text` | `bool` | `True` | Register the `ingest_text` tool. | +| `remove_content` | `bool` | `True` | Register the `remove_content` tool, gated behind confirmation by default. | +| `instructions` | `Optional[str]` | `None` | Custom instructions for the operator agent. When unset, the toolkit's built-in operator instructions are used. | +| `add_instructions` | `bool` | `True` | Whether to add the instructions to the agent's context. | + +`list_content` and `ingest_status` are always registered — they only read. + + +`ingest_path` is off by default, and registering it is an explicit choice: it reads any path the server process can read, and under `scope="shared"` everything it loads becomes readable by every agent on that knowledge base. Enable it only where the operator agent is trusted with the machine's filesystem. + + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `ingest_url` | Ingest a website from its sitemap, one row per page, up to `max_pages` (an optional per-call `max_pages` overrides the default). Re-running refreshes changed pages, retries failed ones, and prunes pages that left the sitemap. | +| `ingest_path` | Ingest a file or folder from the server's filesystem. A folder lands one row per file, refreshed by content digest. Registered only when `ingest_path=True`. | +| `ingest_text` | Ingest a named block of text, with optional metadata. | +| `list_content` | List everything on the knowledge base, grouped by site, with an optional `host` filter. | +| `ingest_status` | Report a site's ingestion status, including failed pages. | +| `remove_content` | Remove a content row by id; removing a site row also removes every page under it. Requires user confirmation by default, and a caller-supplied `requires_confirmation_tools` list is merged with it rather than replacing it. | + +Every tool returns JSON with an `ok` field; failures come back as `{"ok": false, "error": ...}` instead of raising to the model. Each tool also has an async variant registered under the same name, so the async versions are used automatically with `arun` and `aprint_response`. + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/knowledge/management.py) +- [Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/knowledge_management_tools.py) +- [Knowledge Tools](/tools/toolkits/others/knowledge) +- [Knowledge overview](/knowledge/overview) diff --git a/tools/toolkits/others/knowledge.mdx b/tools/toolkits/others/knowledge.mdx index cd325a776..f15769e63 100644 --- a/tools/toolkits/others/knowledge.mdx +++ b/tools/toolkits/others/knowledge.mdx @@ -3,6 +3,10 @@ title: Knowledge Tools description: KnowledgeTools provide intelligent search and analysis capabilities over knowledge bases with reasoning integration. --- + +KnowledgeTools is the read side of knowledge. To ingest, inspect, and remove content with an agent, see [Knowledge Management Tools](/tools/toolkits/others/knowledge-management). + + ## Prerequisites The following example requires the `agno`, `fastembed`, `openai`, and `qdrant-client` libraries. It connects to Qdrant on `localhost:6333`. diff --git a/tools/toolkits/others/wavespeed.mdx b/tools/toolkits/others/wavespeed.mdx new file mode 100644 index 000000000..b824f67a2 --- /dev/null +++ b/tools/toolkits/others/wavespeed.mdx @@ -0,0 +1,84 @@ +--- +title: WaveSpeed +description: "WaveSpeedTools generate images and videos from text prompts through WaveSpeed-hosted models." +--- + + + v3.0.2 + + +**WaveSpeedTools** enable an Agent to generate images and videos from text prompts with models hosted on [WaveSpeed](https://wavespeed.ai). The defaults target `bytedance/seedream-v5.0-pro` for images and `bytedance/seedance-2.5/text-to-video` for video; any id from [WaveSpeed's model catalog](https://wavespeed.ai/models) can be set per instance or per call. + +## Prerequisites + +The following example requires the `wavespeed` and `openai` libraries: + +```shell +uv pip install -U wavespeed openai +``` + +Set the `WAVESPEED_API_KEY` environment variable. Get your key from [WaveSpeed](https://wavespeed.ai). + +```shell +export WAVESPEED_API_KEY=*** +``` + +## Example + +```python cookbook/91_tools/wavespeed_tools.py +from agno.agent import Agent +from agno.models.openai import OpenAIResponses +from agno.tools.wavespeed import WaveSpeedTools + +wavespeed_agent = Agent( + name="WaveSpeed Media Generator Agent", + model=OpenAIResponses(id="gpt-5.5"), + tools=[ + WaveSpeedTools( + image_model="bytedance/seedream-v5.0-pro", + video_model="bytedance/seedance-2.5/text-to-video", + ) + ], + description="You are an AI agent that can generate images and videos using the WaveSpeed API.", + instructions=[ + "When the user asks you to create an image, use the `generate_image` tool.", + "When the user asks you to create a video, use the `generate_video` tool.", + "Return the URL as raw to the user.", + ], + markdown=True, +) + +wavespeed_agent.print_response("Generate an image of a lighthouse on a stormy coast") +``` + +## How Generation Runs + +Both tools submit the job through the WaveSpeed SDK and poll every `poll_interval` seconds until the model finishes or `timeout` elapses — the tool call blocks for the whole wait. Only your prompt is sent: every other setting (aspect ratio, resolution, video duration) uses WaveSpeed's defaults for the selected model. See the [model catalog](https://wavespeed.ai/models) for each model's parameters and limits. + +On success, the tool result names the output URLs and attaches them as image or video artifacts. The media stays on WaveSpeed's side — the bytes are not downloaded — and WaveSpeed keeps generated media for up to 7 days per its [data retention policy](https://wavespeed.ai/docs/data-retention-policy). Failures come back as tool-result strings ("No output received from the model.", or "Error: ..." with the reason), never raised. + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `api_key` | `Optional[str]` | `None` | WaveSpeed API key. If not provided, uses the `WAVESPEED_API_KEY` env variable. | +| `image_model` | `str` | `"bytedance/seedream-v5.0-pro"` | WaveSpeed model id for image generation. | +| `video_model` | `str` | `"bytedance/seedance-2.5/text-to-video"` | WaveSpeed model id for video generation. | +| `poll_interval` | `float` | `1.0` | Seconds between result polls, forwarded to the WaveSpeed SDK. | +| `timeout` | `float` | `600.0` | Wall-clock cap in seconds on one generation, submit to finish. | +| `generate_image` | `bool` | `True` | Enable the generate_image function. | +| `generate_video` | `bool` | `True` | Enable the generate_video function. | +| `all` | `bool` | `False` | Enable all functions. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `generate_image` | Generate one or more images from a text prompt and return them as remote-URL image artifacts. Parameters: `prompt` (str), `model` (Optional[str]) to override the instance's image model for this call. | +| `generate_video` | Generate one or more videos from a text prompt and return them as remote-URL video artifacts. Parameters: `prompt` (str), `model` (Optional[str]) to override the instance's video model for this call. | + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/wavespeed.py) +- [Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/wavespeed_tools.py) +- [WaveSpeed Docs](https://wavespeed.ai/docs) diff --git a/tools/toolkits/others/yfinance.mdx b/tools/toolkits/others/yfinance.mdx index c4aa5f053..c7ab1058a 100644 --- a/tools/toolkits/others/yfinance.mdx +++ b/tools/toolkits/others/yfinance.mdx @@ -5,6 +5,10 @@ description: "YFinanceTools give an agent access to stock prices, fundamentals, **YFinanceTools** enable an Agent to access stock data, financial information and more from Yahoo Finance. + +For one finance toolkit with swappable data providers — Yahoo Finance included — see [Finance](/tools/toolkits/others/finance). + + ## Prerequisites The following example requires the `yfinance` and `openai` libraries. diff --git a/tools/toolkits/overview.mdx b/tools/toolkits/overview.mdx index c49649e02..3c3f3f643 100644 --- a/tools/toolkits/overview.mdx +++ b/tools/toolkits/overview.mdx @@ -140,6 +140,14 @@ The following **Toolkits** are available to use > Tools to search Google, Google News, and Google Scholar, and scrape webpages using Serper. + + Tools for Google web, news, and scholar search via Serply. + + + Tools to give an agent its own email inbox via proof-of-work signup. + Tools to perform calculations. + + One persistent IPython kernel with tools bound as awaitable handles. + Tools to interact with Groq. + + Tools to generate videos with the MiniMax API. + Tools to generate media using Fal. + + One finance toolkit with swappable market-data providers. + Tools to search and analyze knowledge bases. + + Tools to ingest, inspect, and remove knowledge base content. + Tools for data visualization and charting. + + Tools to generate images and videos with WaveSpeed-hosted models. + + v3.0.2 + + +**SerplyTools** enable an Agent to search Google web results, Google News, and Google Scholar through the [Serply](https://serply.io) API, returning results as JSON. + +## Prerequisites + +The following example requires the `requests` and `openai` libraries: + +```shell +uv pip install -U requests openai +``` + +Set the `SERPLY_API_KEY` environment variable. Get your key at [serply.io](https://serply.io); the toolkit sends it as the `X-Api-Key` header. + +```shell +export SERPLY_API_KEY=*** +``` + +Without the key, construction logs a warning and every call returns a JSON error asking for it. + +## Example + +```python cookbook/91_tools/serply_tools.py +from agno.agent import Agent +from agno.tools.serply import SerplyTools + +agent = Agent( + tools=[SerplyTools()], + description="You are a web search agent that finds accurate, up-to-date information.", + instructions=[ + "Use Serply to find the most relevant results for the user's query.", + "Summarize the top results clearly and cite the links.", + ], +) + +agent.print_response( + "What are the latest developments in AI agents?", + markdown=True, + stream=True, +) +``` + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `api_key` | `Optional[str]` | `None` | Serply API key. If not provided, uses the `SERPLY_API_KEY` env variable. | +| `num_results` | `int` | `10` | Default number of results per search. A per-call `num_results` overrides it. | +| `timeout` | `int` | `30` | Request timeout in seconds. | +| `search_web` | `bool` | `True` | Enable the search_web function. | +| `search_news` | `bool` | `False` | Enable the search_news function. | +| `search_scholar` | `bool` | `False` | Enable the search_scholar function. | +| `all` | `bool` | `False` | Enable all functions. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `search_web` | Search Google web results. Parameters: `query` (str), `num_results` (Optional[int]). Returns JSON with `results` (position, title, link, description) and `related_searches`. | +| `search_news` | Search Google News. Parameters: `query` (str), `num_results` (Optional[int]). Returns JSON with `news_results` (title, link, source, published). Serply returns the full news feed regardless of the count, so the toolkit trims it to `num_results`. | +| `search_scholar` | Search Google Scholar for academic papers. Parameters: `query` (str), `num_results` (Optional[int]). Returns JSON with `scholar_results` (title, link, description, authors, citation count, and a PDF link when available). | + +Every failure — a missing key, an HTTP error, or an invalid response — is returned as a JSON error string, never raised. + +Serply serves about ten organic results per page for web search and does not stitch pages, so `num_results` above 10 still returns roughly 10 there; Scholar accepts up to 200. Each page costs one Serply credit, and rate limits depend on your Serply plan — see [Serply's docs](https://serply.io/docs). + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/serply.py) +- [Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/serply_tools.py) +- [Serply Docs](https://serply.io/docs) diff --git a/tools/toolkits/social/atomic-mail.mdx b/tools/toolkits/social/atomic-mail.mdx new file mode 100644 index 000000000..d66978ee9 --- /dev/null +++ b/tools/toolkits/social/atomic-mail.mdx @@ -0,0 +1,87 @@ +--- +title: AtomicMail +description: "AtomicMailTools give an Agno agent its own email inbox through AtomicMail's proof-of-work signup, with no human step." +--- + + + v3.0.2 + + +**AtomicMailTools** give an agent its own email inbox: register an address on [AtomicMail](https://atomicmail.ai), send plain-text email from it, and read what it receives over JMAP. Registration runs through AtomicMail's autonomous proof-of-work signup — no signup form, no domain setup, and no human verification step. + +## Prerequisites + +No extra package is required beyond `agno` — the toolkit uses `httpx`, an Agno core dependency. The example also uses the `openai` library: + +```shell +uv pip install -U agno openai +``` + +```shell +export OPENAI_API_KEY=*** +``` + +No AtomicMail API key is needed up front: `register_inbox` creates the account and stores the key it receives in `credentials.json` under `~/.atomicmail` (override the directory with `credentials_dir` or the `ATOMIC_MAIL_CREDENTIALS_DIR` environment variable), so the same inbox is reused across agent runs. A credentials file that exists but cannot be read raises a `ValueError` instead of being overwritten with a fresh registration. + +## Example + +The following agent registers an inbox and reads it. The first run solves the proof-of-work and takes tens of seconds; later runs reuse the stored credentials: + +```python +from agno.agent import Agent +from agno.models.openai import OpenAIResponses +from agno.tools.atomic_mail import AtomicMailTools + +agent = Agent( + model=OpenAIResponses(id="gpt-5.5"), + tools=[AtomicMailTools()], + markdown=True, +) + +agent.print_response( + "Register the inbox research-agent, then show me the five most recent emails." +) +``` + +## Proof-of-Work Sign-Up + +AtomicMail issues inboxes to agents without a human step. Instead of a signup form, `register_inbox` requests a challenge and solves it locally — an `scrypt` computation whose difficulty AtomicMail sets server-side — then exchanges the solution for a session. AtomicMail uses this in place of CAPTCHAs and manual approval; see the [AtomicMail docs](https://atomic-mail.github.io/atomic-mail-agentic/) for the protocol. + +Three things follow from that design: + +- **The first call is slow.** Expect `register_inbox` to take tens of seconds — AtomicMail quotes roughly 30 seconds. `pow_timeout` (default 300 seconds) caps the solve; a solve that exceeds it returns an `error` result instead of hanging. +- **The solve is parallel.** `pow_workers` threads search the nonce space concurrently, defaulting to `min(4, cpu_count())`. Set `pow_workers=1` to search sequentially. +- **Repeat calls are fast.** Since Agno v3.0.4 the resolved session is cached on the toolkit instance until its token nears expiry, so warm `send_email` and `list_inbox` calls typically take roughly 0.4 to 3 seconds. A cold call — a new process, or an expired token — re-runs the handshake. + +The inbox address is `@atomicmail.ai`. Sending from your own domain requires verifying it in AtomicMail's dashboard, outside the toolkit. AtomicMail publishes its storage quota and rate-limit policy in its [documentation](https://atomic-mail.github.io/atomic-mail-agentic/). + +## Toolkit Params + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `credentials_dir` | `Optional[str]` | `None` | Directory holding `credentials.json`. Defaults to `ATOMIC_MAIL_CREDENTIALS_DIR` or `~/.atomicmail`. | +| `auth_url` | `str` | `"https://auth.atomicmail.ai"` | AtomicMail auth service base URL. | +| `api_url` | `str` | `"https://api.atomicmail.ai"` | AtomicMail JMAP API base URL. | +| `enable_register_inbox` | `bool` | `True` | Enable the register_inbox function. | +| `enable_send_email` | `bool` | `True` | Enable the send_email function. | +| `enable_list_inbox` | `bool` | `True` | Enable the list_inbox function. | +| `all` | `bool` | `False` | Enable all functions. | +| `timeout` | `int` | `30` | Per-request timeout in seconds. | +| `pow_timeout` | `Optional[float]` | `300.0` | Wall-clock cap in seconds for the proof-of-work solve, which is otherwise unbounded and driven by the server-set difficulty. A solve that exceeds it returns an `error` result. `None` waits indefinitely. | +| `pow_workers` | `Optional[int]` | `None` | Threads searching the proof-of-work nonce space in parallel. Defaults to `min(4, cpu_count())`; `1` searches sequentially. | + +## Toolkit Functions + +| Function | Description | +| -------- | ----------- | +| `register_inbox` | Register a new inbox via the proof-of-work signup. Parameters: `username` (str), the inbox local-part, 5-21 characters; `forced` (bool, default False). Idempotent for the same username; refuses to overwrite a different registered inbox unless `forced=True`. Returns the inbox address and account id. | +| `send_email` | Send a plain-text email from the registered inbox. Parameters: `to` (str), `subject` (str), `body` (str). Returns the email and submission ids. | +| `list_inbox` | List the most recent received emails. Parameters: `limit` (int, default 20, capped at 100). The agent's own sent mail is filtered out. Returns id, from, to, subject, received time, and a preview per email. | + +Every function has an async variant registered under the same name, used automatically with `arun` and `aprint_response`. Failures come back as `{"error": ...}` results instead of raising to the model. + +## Developer Resources + +- [Tools](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/atomic_mail.py) +- [Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/atomic_mail_tools.py) +- [AtomicMail Docs](https://atomic-mail.github.io/atomic-mail-agentic/) From 10298a8e84504712901030600f4dcb393c19a3fd Mon Sep 17 00:00:00 2001 From: Himanshu singh Date: Tue, 1 Sep 2026 18:05:47 +0530 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tools/toolkits/social/atomic-mail.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/toolkits/social/atomic-mail.mdx b/tools/toolkits/social/atomic-mail.mdx index d66978ee9..60b5d8fb1 100644 --- a/tools/toolkits/social/atomic-mail.mdx +++ b/tools/toolkits/social/atomic-mail.mdx @@ -7,7 +7,7 @@ description: "AtomicMailTools give an Agno agent its own email inbox through Ato v3.0.2 -**AtomicMailTools** give an agent its own email inbox: register an address on [AtomicMail](https://atomicmail.ai), send plain-text email from it, and read what it receives over JMAP. Registration runs through AtomicMail's autonomous proof-of-work signup — no signup form, no domain setup, and no human verification step. +**AtomicMailTools** give an agent its own email inbox: register an address on [AtomicMail](https://atomicmail.ai), send plain-text email from it, and read what it receives over JMAP. Registration runs through AtomicMail's autonomous proof-of-work signup. There is no signup form, no domain setup, and no human verification step. ## Prerequisites