v3.0.2

agno-agi/agnov3.0.2Aug 30, 2026by ashpreetbedi

AI Summary

This release focuses on behavior changes in metadata precedence, stricter MCP configuration validation, and introduces several new integrations including Synthorai, WaveSpeed, Serply, and AtomicMail. It also enhances support for exposing Agents, Teams, Workflows, and Toolkits as MCP tools.

Key Highlights

  • Metadata precedence updated to component > session > call-site for Agents, Teams, and Workflows.
  • MCPConfig now rejects unknown fields at construction to prevent silent errors.
  • New Synthorai model provider for OpenAI-compatible endpoints.
  • WaveSpeed tools added for generating images and videos via API.
  • Serply search toolkit added for Google web, news, and scholar searches.

Breaking Changes

  • Metadata resolution order changed for Agent, Team, and Workflow components.
  • MCPConfig and MCPServerConfig raise on unrecognised keyword arguments.
  • BaseRemote.acancel_run signature gained an auth_token parameter.
  • Native reasoning detection logic changed for providers like Gemini, Claude, Ollama, and Moonshot.
  • MCP configuration renames: mcp_server= -> mcp=, MCPServerConfig -> MCPConfig, enable_builtin_tools -> default_tools.

New Features

  • Synthorai model provider integration.
  • WaveSpeed image and video generation tools.
  • Serply search toolkit with news and scholar search.
  • AtomicMail toolkit for agent inboxes.
  • Agents, Teams, and Workflows can now be exposed as MCP tools.
  • Toolkits can be exposed as MCP tools with method-level publishing.
  • Context providers now accept query_timeout to prevent hanging runs.

Full Release Notes

# Changelog

## **Behavior Changes**

- **Run metadata precedence**: `metadata` now resolves as component, then session, then call-site on `Agent`, `Team`, and `Workflow`, so a `metadata=` passed to `run()` wins over `agent.metadata` where the component value previously won. A run no longer assigns session metadata back onto the shared component, so code that read `agent.metadata` after a run to observe session values now sees the constructor value. The session layer only applies where the dispatch pre-reads the session, so `Team.arun` and the async-DB agent and workflow paths still resolve from component and call-site alone. (#9104)
- **`MCPConfig` rejects unknown fields**: `MCPConfig`/`MCPServerConfig` now raise on unrecognised keyword arguments at construction instead of ignoring them, so a typo such as `tool=` fails at boot rather than silently serving a different tool surface. (#9819)
- **`BaseRemote.acancel_run` signature**: the abstract method gained an `auth_token` parameter that the cancel surfaces pass by keyword, so a third-party `BaseRemote` subclass must accept it. (#9819)
- **Reasoning detection asks the provider**: native reasoning detection now queries the provider before falling back to model-id matching, so a `Gemini` or `Claude` model configured for thinking is classified as non-reasoning when the provider reports thinking unsupported. The lookup is a blocking HTTP call cached on the reasoning manager, with a 10 second timeout on the Ollama, OpenRouter, and Moonshot paths. Id-based fallbacks changed too: `gpt-5` variants match on OpenAI and Azure OpenAI, Groq and Ollama match `gpt-oss` and `qwen3`, and Ollama's `qwen2.5-coder` is no longer treated as a reasoning model. (#8616)
- **MCP configuration renames**: `AgentOS(mcp=...)`, `MCPConfig`, and `default_tools` are the new spellings for `mcp_server=`, `MCPServerConfig`, and `enable_builtin_tools`. The old names keep working as aliases with removal targeted for 3.1; passing both spellings with different values raises. (#9819)

## **New Integrations**

- **Synthorai model provider**: `Synthorai` (`agno.models.synthorai`) talks to the Synthorai gateway over its OpenAI-compatible endpoint, reading `SYNTHORAI_API_KEY` and defaulting to `https://synthorai.io/v1`. It is registered in the provider lookup table, so `model="synthorai:<model-id>"` strings resolve as well. (#9788)
- **WaveSpeed image and video generation**: `WaveSpeedTools` (`pip install agno[wavespeed]`, key from `WAVESPEED_API_KEY`) generates media through the WaveSpeed API. `generate_image` and `generate_video` take a text prompt and return a `ToolResult` carrying `Image`/`Video` artifacts, polling synchronously within `poll_interval` and `timeout`. (#9620, fixes #9621)
- **Serply search toolkit**: `SerplyTools` searches Google web, News, and Scholar through the Serply API, reading `SERPLY_API_KEY`. Web search is on by default; `search_news`, `search_scholar`, or `all=True` enable the others. A missing key or failed request returns an `error` field instead of raising. (#9780, fixes #9779)
- **AtomicMail toolkit**: `AtomicMailTools` gives an agent its own inbox. `register_inbox` provisions one through AtomicMail's proof-of-work signup with no domain setup or human verification, and `send_email` and `list_inbox` work over JMAP. Credentials are cached to `~/.atomicmail/credentials.json` so later runs reuse the same inbox, and `pow_timeout` (default 300s) caps the solve. (#9130)

## **Improvements**

- **Agents, teams, and workflows as MCP tools**: `MCPConfig.tools` now accepts `Agent`, `Team`, and `Workflow` instances, remote proxies, and component factories, publishing each as its own named MCP tool — `chief`, rather than `run_agent(agent_id="chief")`. `component.as_tool(name=..., description=...)` publishes one under a name and description of your choosing. `continue_run` and `cancel_run` register alongside exposed components even with `default_tools=False`, so a run that pauses on a confirmation stays resumable over MCP. (#9819)
- **Toolkits as MCP tools**: `MCPConfig.tools` now accepts a `Toolkit` and publishes one MCP tool per registered method, narrowed by the toolkit's own `enable_*`/`include_tools`/`exclude_tools`, where it previously raised `TypeError`. Framework parameters (`RunContext`, `Agent`, `Team`, and the `_agno_*` channels) are kept out of the client-facing schema and filled server-side. A tool returning a `ToolResult` is rendered as MCP content blocks — text, image and audio, embedded resources for video and file bytes, and `resource_link` for url-only artifacts. A `**kwargs` entrypoint, which previously took `get_app()` down, now publishes its declared schema or its named parameters. (#9846)
- **MCP tool titles and behaviour annotations**: `as_tool()` and `@tool`/`Function` now accept `title` and `annotations`, which AgentOS publishes over MCP for exposed components, custom tools, and its eight built-in tools. Exposed components publish a title even when you set none and assert `readOnlyHint: False`, `destructiveHint: True`, `openWorldHint: True` by default, with your overrides merged per key. Unknown annotation keys raise rather than travelling to the client. (#9844)
- **Context provider `query_timeout` and `write_tools`**: every context provider accepts `query_timeout`, a wall-clock deadline applied to each `query_<id>` tool call that yields an error chunk instead of hanging the run. It needs Python 3.11 or later and raises at construction below that. The five write-capable providers also accept `write_tools` to replace the default write sub-agent toolset. (#9104)
- **Wiki `GitBackend` keeps the PAT off disk**: the token is injected per git call through an ephemeral credential helper instead of being baked into the `origin` URL, and existing clones are rewritten to the bare URL on setup. This needs git 2.31 or later. (#9104)
- **Slack delivery options and safer approval cards**: the Slack interface gains `markdown`, `unfurl_links`, and `unfurl_media`, now sent explicitly on every message. Approval cards make backticks, newlines, and angle brackets in model-produced tool args inert so they cannot break out of the inline code span. (#9104)
- **Headless Google OAuth**: Google toolkits accept `AuthConfig(interactive=False)`, or `GOOGLE_OAUTH_NONINTERACTIVE=1`, to raise instead of blocking on a browser OAuth flow that will never complete on a headless host. (#9104)
- **Schedule listing**: new `ScheduleManager.list_all()` and `alist_all()` page the whole schedule catalog and surface database errors instead of returning an empty catalog, backed by a new `raise_on_error` argument on `get_schedules`. Listings now break `created_at` ties by `id`, so rows sharing a timestamp are no longer skipped or duplicated across pages. (#9104)
- **Moonshot and OpenRouter reasoning**: `MoonShot` (Kimi) gains sync, async, and streaming reasoning handlers that read `reasoning_content`, and `OpenRouter` is routed through the OpenAI reasoning path. Previously both were picked up only when their id happened to contain `deepseek-r1` or `minimax-m2`/`m3`. (#8616)
- **MCP configs scoped down to zero tools now warn**: `MCPConfig` logs a warning at construction when the default tools are on but `include_tags`/`exclude_tags` scope out every tag and no custom `tools` were passed — the config that boots a `/mcp` endpoint listing nothing. The config is still accepted and the resolved tool surface is unchanged. (#9748)

## **Bug Fixes**

- **`CodeMode(allow_shell=False)` on IPython 9.17**: IPython 9.17 registers script magics lazily and recreates them on lookup, so removing `bash` from the cell-magic table no longer disabled it — `%%bash` still ran in a kernel configured to forbid shell access. The kernel now materialises the script-magic provider first and drops `bash` from both the lazy table and the live registry, so loading a sibling magic such as `%%sh` cannot re-register it.
- **Registry MCP toolkits from standalone processes**: `StudioTools` now connects an unconnected registry MCP toolkit on demand while resolving tools, so creating or editing a component from a script, notebook, or eval run no longer fails with "Toolkits have no functions and cannot be persisted". `eval.suite.cli`/`acli` take a new `mcp_tools=[...]` argument that connects those toolkits before the cases run, and `MCPToolbox` clears its client state on `close()` and on a failed filter so a reconnect re-applies `toolsets`/`tool_name`. (#9845)
- **Executor errors in streaming workflow steps**: when a `Step`'s `Agent` or `Team` executor failed mid-stream, the streaming paths treated the error event as a finished step and emitted an empty `StepOutput` with `success=True`. `Step.execute_stream` and `Step.aexecute_stream` now raise a `RuntimeError` naming the step and its executor, so the failure goes through normal step error handling and the resulting `StepOutput` carries `success=False` and the error text. Failing streaming steps are now retried like any other step failure. (#9138, fixes #7185)
- **Truncated tool arguments in the paused-run panel**: the human-in-the-loop panel built its argument list with `rstrip(", ")`, which strips a set of characters rather than a suffix and so also ate trailing commas and spaces belonging to the last argument's own value. All three blocks now join arguments the way `format_tool_calls` already did. This is display-only; the arguments passed to the tool were never affected. (#9246, fixes #9248)

## **Cookbooks**

- Cookbook examples that pinned `gpt-4o`, `gpt-4o-mini`, or `gpt-5.4-mini` now use `gpt-5.6-luna`, across 355 files. Gateway examples were rewritten too, so `LiteLLM`, `OpenRouter`, `AzureOpenAI`, `AzureAIFoundry`, `CometAPI`, `Requesty`, `LangDB`, and `AIMLAPI` examples depend on that gateway or Azure deployment resolving `gpt-5.6-luna`. Specialized ids and dated snapshots are unchanged. (#8939)