github agno-agi/agno v3.0.2

3 hours ago

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)

Don't miss a new agno release

NewReleases is sending notifications on new releases.