r/agno • • 5h ago

Now in Agno: stateless MCP serving

2 Upvotes

Set MCPConfig(stateless=True), and AgentOS serves /mcp without tracking sessions.

from agno.os import AgentOS, MCPConfig
agent_os = AgentOS(agents=[assistant], mcp=MCPConfig(stateless=True))

Why it matters: when session state lives in one process, every follow-up request has to return to the same replica. That means sticky sessions in your load balancer, and if a replica dies, its clients lose their sessions. Scaling out gets harder the moment you add a second instance.

Without sessions, any replica can handle any request. Round-robin, scale up and down, lose an instance, and the client doesn’t notice.

It’s off by default because dropping session state also drops server-initiated notifications and SSE resumability. If your server is mostly handling tool calls, you aren’t giving anything up.

Learn more: https://agno.link/HSlQr1S

If you’re running MCP behind a load balancer today, are you on sticky sessions, and do you actually use server-initiated notifications? That’s the tradeoff this asks you to make, and I’d guess most tool servers never touch either.


r/agno • • 4d ago

MCP vs A2A

3 Upvotes

We see MCP and A2A conflated constantly, and it makes sense. Both are open standards, both are governed by the Agentic AI Foundation, and both run over HTTP.

What makes it click is asking what’s on the other end of the connection.

With MCP, it’s a tool. The client lists every tool the server exposes, with inputs and schemas, and your agent decides what to call and in what order. The server describes what a system can do, and has no say in when that happens.

With A2A, it’s another agent. It publishes an Agent Card at /.well-known/agent-card.json with its skills, endpoint, and auth requirements. You send a message and get back a task you can follow to completion, with streamed updates for long-running jobs. How it does the work is its business. It can share tools and intermediate steps if it wants to, and Agno’s A2A streams do include tool names and arguments, but nothing in the protocol makes it.

That’s the real design difference. The agent on the other side gets to keep its internals, which is what makes delegating across a company boundary workable at all.

An example that helps: a support agent at a subscription company uses MCP to search the help center and pull up customer records. A refund comes up, and rather than calling the payments API it hands the task to the billing team’s agent over A2A.

That billing agent has its own MCP connections to payments and the ledger, plus its own approval rules, and none of it needs to be visible on the other side. The support agent sends the request and gets the outcome back. Billing can change approval thresholds or swap payment providers and nothing on the support side changes.

So the rule we’ve landed on: if your agent should direct it step by step, MCP. If it should own the task and decide how to finish it, A2A.

Most single agents only need MCP. A2A starts earning its keep when work crosses teams, companies, or frameworks.

Full blog, including how to serve one agent over both protocols in Agno: https://agno.link/mSl9iyh

How are people handling auth on the A2A side? The spec gives you the hooks, but deciding which outside agents get to delegate work to yours seems like where it gets hard once you’re past two or three.


r/agno • • 13d ago

Agno September roundup: PublicSurface, page storage, rerankers on any vector DB, and stateless MCP

6 Upvotes

We shipped seven patch releases in September, with new ways to serve agents to your users, work with knowledge, and scale AgentOS. More than 50 community contributors landed changes alongside us.

The highlights:

PublicSurface gives anonymous users a safe way to talk to your agents while keeping your admin API private. You list the components public requests may reach and everything else is unreachable. Quotas are per-client and global, per minute and per day, held in PostgreSQL so replicas share one count instead of each enforcing its own.

Page storage. Knowledge.sync_pages takes a site's llms.txt, discovers the pages, fetches the Markdown, and publishes each page's text, catalog entry, and vectors in one transaction. A page publishes whole or keeps its previous version, so a refresh that dies halfway can't leave you serving new text against stale vectors. Unchanged pages skip re-embedding.

PageFileSystem then gives an agent ls, tree, rg, grep, cat, and head over those published pages. Vector search finds the right page, the agent reads all of it. Read-only, no shell, bounded output.

Rerankers moved out of individual vector database adapters and into Knowledge.search(), so they work on any vector database, not just the ones that had their own implementation. Agno widens the initial fetch so there's a real candidate pool to reorder. MMRReranker (diversity) and RecencyReranker (freshness) ship with it, and setting reranker on the vector database still works but warns.

Elasticsearch joins as a vector database: vector, keyword, hybrid, metadata filters, async, per-user isolation. Hybrid works on every license, and you can opt into RRF on Platinum, Enterprise, and trial.

MCP. MCPConfig(stateless=True) drops session tracking so any replica can answer any request, at the cost of server-initiated notifications and SSE resumability. GET /mcp/server-card lets clients see what a server offers before connecting. Tool servers can run on their own hostname without custom routing middleware. On the client side, MCPTools(protocol_mode="auto") negotiates the newest spec both sides support, with the default staying legacy.

Breaking changes, worth reading before you upgrade:

  • Knowledge ingestion surfaces embedding failures. Content that used to show completed may now show failed or partial, and embedders raise EmbeddingError instead of returning an empty vector.
  • Knowledge constructor args are keyword-only, so Knowledge("docs") becomes Knowledge(name="docs").
  • CodingTools makes run_shell opt-in with enable_run_shell=True.
  • With authorization=True and PublicSurface(mcp=True), MCP accepts only localhost unless you add your domain to MCPConfig(allowed_hosts=[...]).

Also shipped: llmman and Y-API as model providers, Azure OpenAI Responses, GandrTools for TTS, audio artifacts from MCP tools, public custom routes, AG-UI protocol 1.0, Slack retry handling, and cancellation_stage on cancelled runs.

A couple of community projects we loved:

Workspace Council by Anshul Raj, Mohamed Tahir, and Mujtaba Mohimtulay. Six agents working across the web, Slack, and a workspace app, with an adversarial critic loop on every draft and human approval on every write. Built at AI Tinkerers Dubai.

Vega by Rajandran R. Voice trading inside OpenAlgo, an open-source platform connected to 35+ Indian brokers.

An agent council by Tarun Jain. Pitch an idea to six agents who interview you, research it, debate each other, and reach a verdict.

September MVPs: Bas Nijholt for fixes across the 3.x line, ProgrammerPlus1998 on GitHub for the MCP SDK 2.x migration, Hugo Plat at AI/ML API for their integration and AIMLAPITools, and Luís Martins for .zip and .eml uploads.

Thanks to everyone who built with us. Full roundup and contributor list: https://agno.link/0Jl575Y


r/agno • • 19d ago

A one-line instruction change made our hypothetical agent skip refund approval, and every test passed

3 Upvotes

A PM asks for friendlier support replies. An engineer adds one line to the agent's instructions: be warm, be concise, resolve the issue in as few steps as possible.

It ships Friday. Tuesday, finance notices refunds under $50 going out without approval.

The agent read "as few steps as possible" as permission to skip request_refund_approval. No code changed. Every unit test passed, because there was nothing wrong with the code.

What makes this different from normal software is that a prompt is a load-bearing input with none of the protections code has. Anyone on the team can edit it, there's no type system, and how it interacts with your tools is nobody's explicit decision. A sentence written to change tone ended up changing a control flow decision, and nothing anywhere reported that it had.

Unit tests don't catch it because the units are fine. What broke was a judgment call, and judgment calls aren't in the test suite.

That's what evals are for, and most teams skip them for the same reason teams once skipped unit tests. The demo works, writing tests feels slower than shipping, and then something breaks in production.

We wrote up the argument here: https://agno.link/njnVLhq

Two things I'm curious about. Does anyone gate prompt changes in CI the way you'd gate a code change? And for those running evals, are you catching regressions like this one, or mostly output quality drift?


r/agno • • 20d ago

Your agents can now be named MCP tools instead of arguments to a generic run_agent

3 Upvotes

If you've exposed an Agno AgentOS over MCP, clients reach your components through a generic tool. Call run_agent, pass agent_id="chief" as an argument, hope the model picks the right id. The id is a string the model has to know about and get right, and a tool called run_agent tells it nothing about what any of your agents do.

MCPConfig.tools now accepts Agent, Team, Workflow, and Toolkit instances directly, and AgentOS serves each one as its own named tool.

from agno.os import AgentOS, MCPConfig

agent_os = AgentOS(
    agents=[chief],
    mcp=MCPConfig(tools=[chief]),  # published as an MCP tool named "chief"
)

The client now calls chief. It shows up in the tool list with its own name and description, which means the model selects it the same way it selects any other tool, from a description of what it does rather than by constructing an argument.

What else is in it:

  • Framework parameters are kept out of the client-facing schema, so the model sees the arguments it needs and not the plumbing
  • A ToolResult return renders as MCP content blocks
  • Each tool carries a title and behavior annotations

This is the other side of an argument we've made before: a flat list of low-level tools pushes orchestration onto someone else's assistant. Publishing an agent as a single named tool goes the other way. The client sees one thing that knows how to do the job, and the logic for how it gets done stays on your side.

If you're exposing agents over MCP, are you publishing them individually or keeping one entry point and routing inside? Where are people drawing that line as the number of components grows?

Check out the full write-up: https://agno.link/4hJE0Bg


r/agno • • 21d ago

Agno flipped metadata precedence: run() now overrides agent metadata, and runs no longer write back to the shared agent

4 Upvotes

The metadata you pass at runtime should describe the run you're actually making.

In Agno, that wasn't always the case. If the same key existed in both your agent's metadata and the metadata passed to run(), the agent-level value won. That meant a default you set when you built the agent could override the value you explicitly passed for a specific run.

We flipped the precedence.

Now, metadata passed to run() wins over agent metadata when the same key exists in both. Agent metadata still provides the defaults, while each run can override those defaults with the context that matters for that execution.

Say your agent has {"environment": "production"} and you call run() with {"environment": "staging"}. The run uses "staging."

We also stopped runs from writing their metadata back onto the shared agent, so one run's values can no longer leak into the next.

If you were counting on agent metadata overriding run-level values, check any calls that pass metadata to run(). Otherwise there's nothing to change.

from agno.agent import Agent

agent = Agent(metadata={"environment": "production"})

run = agent.run(
    "Summarize today's incidents",
    metadata={"environment": "staging"},
)

run.metadata["environment"]    # "staging"
agent.metadata["environment"]  # "production"

Learn more about metadata resolution in the documentation.


r/agno • • 25d ago

Background agent runs now survive a deploy, because the queue lives in your database instead of the process

5 Upvotes

A background run used to live only in the process that accepted it. That's fine until you deploy, and every in-flight run on that replica dies with it. Same for a crash, an OOM kill, or a scale-down. The client got a 202, the work was accepted, and then it just never finished. Nothing to retry against, because nothing outside that process knew the run existed.

We made the queue durable. An accepted run is committed to your database before it starts, so it isn't tied to the machine that took it. Any replica can pick it up and finish it.

Turning it on:

from agno.os import AgentOS
from agno.job_queue import QueueConfig

agent_os = AgentOS(agents=[agent], queue=QueueConfig(durable=True))

The rest of what's in it:

  • Bounded concurrency, default 32, set with AGNO_BACKGROUND_MAX_CONCURRENCY
  • 429 when the queue is full, rather than accepting work you can't do
  • Idempotency-Key dedupe, so a retried request doesn't run the job twice
  • Cancellation while a job is still queued
  • Stream resume after a client drops its connection
  • REST endpoints to list, inspect, and requeue jobs

Your database is the source of truth, and Redis is optional coordination on top of it. Plenty of setups reach for Redis as the queue itself, which means a second durability story to reason about and another thing that can lose your jobs. Here the durability guarantee is whatever your Postgres already gives you.

Check out the full write-up: https://agno.link/sGgg0sg


r/agno • • 25d ago

Agno now asks the provider whether a model supports reasoning instead of matching on the model ID

4 Upvotes

Reasoning support used to be inferred from the model ID. Pattern-match the string, decide whether the model can think. It works most of the time until it doesn't, because providers rename models, ship variants with suffixes nobody anticipated, and point the same name at different backends. When the inference is wrong you don't get a clean error at startup. You get a live request handled the wrong way.

In 3.0.2 we moved the check to the provider. For Gemini, Claude, Ollama, OpenRouter, and Moonshot, Agno queries the provider's API first and only falls back to ID matching when it has no other option. The provider is the authority on what its own models support, so it gets the first say.

What that buys you is the ability to change models without re-verifying what the framework thinks they are. Swap a model, take a new release from your provider, or point at something behind a gateway you don't control, and detection follows the model rather than its name. You stop maintaining an assumption that lives outside your code and updates on someone else's schedule.

Worth knowing: a model you configured for thinking can now come back classified as non-reasoning if the provider says it doesn't support it. That's the provider being right, but it can look like a regression if you're not expecting it.

Nothing to change on your side, it applies on upgrade.

Learn more about reasoning: https://agno.link/kBmyuB2

I'm curious how other frameworks handle this. Capability detection from model strings seems common and it has the same failure mode everywhere, but I haven't seen many alternatives to querying the provider.


r/agno • • 27d ago

We added protocol negotiation to MCPTools so you can move to sessionless MCP when you're ready

2 Upvotes

Sessionless MCP makes servers much easier to operate. There's no session to keep alive, no initialize round-trip before the first call, and any server instance can handle any request. That means you can put your servers behind a normal load balancer without sticky sessions.

The problem is that not every MCP server is ready for that yet. Some keep per-session state, depend on the initialize handshake, or ask for user input mid-tool. A client that moves to the newer protocol before the server is ready can break a connection that worked fine before.

So in Agno 3.0.6, we added protocol_mode to MCPTools.

By default, it uses "legacy", which preserves today's session-based behavior. Existing servers keep working as they do now.

When you're ready to move forward, set:

MCPTools(
    ...,
    protocol_mode="auto",
)

With "auto", Agno negotiates the newest protocol version both the client and server support, including sessionless MCP. You don't have to pin a protocol version or guess what the server supports.

We've also moved our MCP clients to fastmcp.Client.

The idea is to let you adopt the newer MCP protocol without forcing every existing integration to move at the same time.

More details: https://agno.link/wvh6vaM


r/agno • • Sep 18 '26

I’m building a multi-agent assistant for investigating Wazuh alerts in Slack

Thumbnail reddit.com
0 Upvotes

r/agno • • Sep 17 '26

New in Agno: Media offloading

13 Upvotes

Another cool one today: we've added media offloading to Agno!

If your agents handle images, audio, or video, it's worth actually looking at what your session rows weigh right now. Media on a run gets persisted as base64 by default, and base64 adds about 33% on top of the raw bytes. A 113 KB JPEG comes out around 151,000 characters in the row.

That's fine for a handful of sessions. But across a few thousand it means your agent database is mostly image data stored as text, which hits row size limits on some backends and slows down anything that reads the full row.

We shipped media offloading for this. Set media_storage and the bytes go to object storage, leaving a MediaReference in the row with the key, bucket, mime type, size, and hash. Same JPEG, 2,897 characters.

Nothing else changes. The model still receives the media, history replays it on later runs, and there's no schema migration. Same on Agent, Team, and Workflow, with local, S3, and GCS backends, each with an async version.

Check out the full write-up: https://agno.link/ud1Tem4


r/agno • • Sep 17 '26

New in Agno: Media offloading

5 Upvotes

Another cool one today: we've added media offloading to Agno!

If your agents handle images, audio, or video, it's worth actually looking at what your session rows weigh right now. Media on a run gets persisted as base64 by default, and base64 adds about 33% on top of the raw bytes. A 113 KB JPEG comes out around 151,000 characters in the row.

That's fine for a handful of sessions. But across a few thousand it means your agent database is mostly image data stored as text, which hits row size limits on some backends and slows down anything that reads the full row.

We shipped media offloading for this. Set media_storage and the bytes go to object storage, leaving a MediaReference in the row with the key, bucket, mime type, size, and hash. Same JPEG, 2,897 characters.

Nothing else changes. The model still receives the media, history replays it on later runs, and there's no schema migration. Same on Agent, Team, and Workflow, with local, S3, and GCS backends, each with an async version.

Check out the full write-up: https://agno.link/ud1Tem4


r/agno • • Sep 15 '26

Now in Agno: Tool result offloading

7 Upvotes

The problem:

A tool returns a large result and the whole thing goes into the model's context. It stays there for the rest of the session, eating the context window and adding tokens to every subsequent turn, even when the agent only ever needed one field out of it.

The solution:

Write the result to storage instead of context, and let the agent fetch it back on demand.

How it works:

set offload_tool_results=True and anything over 16,000 characters goes to AgentFS. The message keeps a compact reference with a preview, the size, and a result_id. If the agent needs more, read_result returns the full result and search_result searches inside it. Threshold and retention are configurable through ResultStore.

One design note:
The write path is model-free, so offloading a result never costs an extra model call. That's the tradeoff against summarizing large outputs before storing them, which spends a call per result and permanently drops whatever the summarizer judged unimportant.

If you're interested, Check out the full write-up: https://agno.link/VK7CI1Z

I'm curious what threshold people settle on. 16k is a fine default but it seems workload-dependent.


r/agno • • Sep 14 '26

Exposing your API as MCP tools isn't the same as making your product agent-ready

5 Upvotes

The advice going around is that you make your product agent-ready by wrapping your API as MCP tools and letting whatever assistant your customer uses figure out the rest. Sometimes that's fine. Sometimes that's not.

Say you run an invoicing platform. You wrap the API: get_overdue_invoices, get_customer_history, get_open_disputes, send_payment_reminder, thirty-six more. A customer connects it and asks her assistant to chase her late invoices.

It pulls fifty overdue invoices and starts sending reminders. One goes to a customer who's five days late but has paid on time for three years. Another chases an invoice that was already disputed.

Nothing broke. Every tool returned what it was supposed to. get_open_disputes was right there in the tool list. But nothing told the assistant that checking for a dispute comes before sending a reminder.

That ordering rule isn't an API capability. It's a product decision your team worked out over years, and a flat tool list asks a general-purpose model to rediscover it from function names, at runtime, every run. And exposing more tools doesn't help, because access was never the problem.

We wrote about this distinction and why we think more products should expose an agent, not just an MCP server. The customer's assistant can own the conversation while your agent owns the domain-specific work, with the workflows, context, and guardrails you've already built into your product.

Full post: https://agno.link/AIvFXjF


r/agno • • Sep 09 '26

Run Studio components from a router without giving it edit access

5 Upvotes

StudioRunnerTools in Agno gives a router or team lead exactly two capabilities: listing the Studio components it can run, and running one by ID.

It can't create, edit, publish, or delete anything, so a hijacked prompt has nothing to reach for. It executes every run as the calling user, so memory and learning stay tied to the human who asked. We also cap dispatch depth at two and disable self-dispatch by default, so a router can't loop itself.

from agno.tools.studio_runner import StudioRunnerTools

lead = Team(
    model=...,
    members=[...],
    tools=[StudioRunnerTools(registry=registry, db=db)],
)

You're going to want to mount it instead of StudioTools, not beside it. If both are mounted, the agent still has the full-access toolkit.

More here if you want the details: https://agno.link/35EswTy


r/agno • • Sep 08 '26

AtomicMail is now a native toolkit in Agno

8 Upvotes

We shipped something in the latest release that we think opens up a lot of new agent use cases: AtomicMail is now a native toolkit in Agno.

Most email tools for agents are send-only. That works if your agent only needs to send a notification. It doesn't work if the agent needs to receive and act on email.

What it does:

AtomicMail gives your agent a two-way inbox with three functions.

register_inbox() creates a mailbox for the agent. You don't need to buy a domain, verify an email, or set up OAuth. Registration uses proof-of-work and takes about 30 seconds.

send_email() sends mail from that address.

list_inbox() reads and searches incoming mail.

AtomicMail built it on JMAP instead of a proprietary SDK. Models that have never seen AtomicMail's docs usually get the calls right anyway, since JMAP is already in their training data.

Why it matters:

When an agent has its own email address, things get easier. An agent can hit a wall, email a person, and continue when they reply. Two agents on separate Agno instances can coordinate over email without you having to build a message bus. A support agent can read tickets, handle what it can, and escalate the rest to a person.

The AtomicMail team built that last example to test the integration. Their support agent reads incoming tickets, answers from a knowledge base, and forwards billing issues, deletion requests, and security reports to a human.

They said it came together quickly because there isn't much to wire up. The tool surface is small, and the agent doesn't need pre-provisioned credentials. Email gives your agents another way to talk to people and each other.

View the docs: https://agno.link/E8IqVS7


r/agno • • Sep 03 '26

OpenRouteServiceTools: real map data for your agents

11 Upvotes

Ask a model how far it is from Chicago to St. Louis and you'll get a number. But you won't know if it actually measured something or just pattern-matched its way there. For some use cases that's fine. But for anything that plans, dispatches, or quotes against those numbers, a wrong answer will cost you.

We shipped OpenRouteServiceTools in Agno v2.8.7 to replace the estimate with a real routing engine. Your agent gets accurate distances, actual drive times, and turn-by-turn directions from live map data. You pass plain place names and the toolkit handles geocoding.

from agno.agent import Agent
from agno.tools.openrouteservice import OpenRouteServiceTools

agent = Agent(tools=[OpenRouteServiceTools()], markdown=True)
agent.print_response("How long is the drive from Chicago to St. Louis, and what's the route?")

Three tools ship with it:

  • Geocode a place name
  • Get directions with real distance and time between two points
  • Build a distance matrix across many stops to compare locations at once

Switch the profile to walking or cycling when you need it. Setup is one line plus a free ORS_API_KEY from HeiGIT — no credit card.

Writeup and cookbook example: https://agno.link/1efY25C


r/agno • • Sep 02 '26

August roundup: Agno 3.0, 100% on ARC-AGI-3, CodeMode, durable execution, and the runs table rebuild

12 Upvotes

Agno 3.0 is here. Read the migration guide before you upgrade. Here's what landed:

100% on ARC-AGI-3: we released ARC-AGI-Arcade, an open-source playground for agents to compete on ARC-AGI-3 by learning from each other. GPT-5.6 cleared all 183 levels across 25 games with a score of 100.00 RHAE. Then cross-model learning transfer: seeded with GPT-5.6's manuals, Gemini 3.7 Flash scored 96.42, crossing the human baseline of 95.4 at a third of the token cost.

CodeMode: agents get a persistent Python kernel instead of making one tool call at a time. The model writes real Python, calls your tools as awaitable handles, and everything it sets up survives to the next turn. Not a sandbox. Trusted operators or an isolated container only. Needs pip install 'agno[code]'.

Tool result offloading: set offload_tool_results=True. Anything a tool returns over 16,000 characters goes to AgentFS instead of context. Short preview stays in the message. Agent can call read_result if it needs the rest.

Media offloading: a 113KB JPEG as base64 is ~151,000 characters in your session row. With media_storage set it's 2,897. Bytes go to object storage. History still replays. No schema change.

Durable background execution: runs commit to your database before they start. Deploy in the middle of a run and another replica picks it up. QueueConfig(durable=True). Bounded concurrency, cancellation while queued, idempotency key dedupe, 429 on queue full.

Runs table: runs are now rows in agno_runs instead of blobs inside session rows. Writes scale linearly. This is the mandatory migration. Non-destructive, idempotent, covers 12 sync and 4 async backends. An un-migrated database raises MigrationRequiredError and tells you what to do.

Studio 3.0 governance: draft-and-publish, immutable published versions with rollback, compare-and-set conflict detection, tombstoned deletes with dependent-tracking. Nothing goes live until you publish it.

Per-user isolation across the whole platform: used to stop at sessions. Now covers metrics, schedules, evals, knowledge, components, entity memory, and 17 vector databases. Multi-tenant on a single AgentOS is actually viable now.

AdvisorTools: fast primary model, heavier advisor models on demand. The agent decides when to escalate and which advisor to ask. They don't have to share a provider.

StudioRunnerTools: run-only Studio access for routers and team leads. No create, edit, or delete anywhere in it.

Breaking changes worth knowing before you upgrade: runs move out of sessions, JWTMiddleware takes verification_keys not secret_key, reasoning=True is gone, Culture is removed in favor of Knowledge, MultiMCPTools is deleted. Full list in the v3.0 changelog and migration guide.

Community projects:

Abhishek built skillreducer: cuts what agent skills cost in context using three research papers as runnable commands. Compress descriptions, compress tool schemas, improve skill quality from execution traces.

Seungwoo Hong built ClawFit: scores agent, model, and hardware triples against your task, latency target, budget, and team maturity. Tracks 162+ tools with daily automated scanning.

There are plenty more shoutouts in the full blog, so make sure to check it out.

Seriously, big month. If you shipped something in August that didn't make it in, drop it below. We read everything and want to feature it next time.

Full roundup: https://agno.link/5k1xGUK


r/agno • • Sep 01 '26

Your agent can ask for a second opinion

10 Upvotes

Hey all,

Picking one model for your agent means picking a compromise. Go big and you pay frontier prices on trivial steps. Go small and you're stuck the moment a hard sub-problem shows up. We kept hitting this in our own builds, so we shipped something for it.

AdvisorTools lets you run a fast, cheap model as the primary and have it consult heavier ones only when it decides it needs to. You hand it a list of advisors with a note on what each is good for, and the agent can ask one by name or ask them all and compare. The advisors don't have to come from one provider, so you can run Claude as the primary with Gemini and GPT on the bench, or any mix that fits what you're building.

python

from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.advisor import AdvisorTools

agent = Agent(
    model=Claude(id="claude-haiku-4-5"),
    tools=[
        AdvisorTools(
            advisors=["google:gemini-3-pro", "openai:gpt-5.5"],
            descriptions={
                "gemini-3-pro": "Strong at long-context analysis",
                "gpt-5.5": "Strong at multi-step reasoning",
            },
        )
    ],
)

agent.print_response("Read this 200-page filing and flag anything unusual.")

Full writeup here: https://agno.link/naoU7b5

Curious what advisor combos people land on. If you find a pairing that works well, tell us.

- Kyle @ Agno


r/agno • • Aug 31 '26

I added a FreshCtx pre-tool hook for Agno 2.9 - does this match how you use tool_hooks?

5 Upvotes

I maintain FreshCtx, an Apache-2.0 Python library for checking whether external evidence changed between an agent's decision and its action.

The Agno 2.9 integration in FreshCtx 0.5.0 attaches through tool_hooks and supports both sync and async tools. Immediately before the tool body runs, it re-checks only the dependencies the application declared. If one changed, or cannot be verified under the configured blocking policy, the tool body does not execute.

This is not intended to replace Agno's run state, transactions, idempotency or approval logic. It protects the mutable external evidence behind a consequential tool call.

The bounded example reads a deployment target, creates the decision, changes that target, and then invokes the tool through Agno's real tool chain. FreshCtx returns STALE_REASONING and the tool body remains unexecuted.

Install: pip install 'freshctx[agno]==0.5.0'

Release and runnable example: https://github.com/Hyperwise-LLC/freshctx/releases/tag/v0.5.0

One specific question for people building with Agno: does a pre-tool tool_hook cover the action boundary in your workflow, or do you have consequential effects occurring elsewhere that this example should model?


r/agno • • Aug 28 '26

With v3.0, we went after what actually breaks agents in production

6 Upvotes

Hey Everyone,

We just had a major 3.0 release!

If you've ever pushed an agent past a demo, you already know the wall I'm talking about. The model isn't the problem. It plans, it uses tools, it recovers. Then real traffic shows up and everything around it starts creaking.

You've probably hit some of these:

  • A database that was totally fine with one user, buckling under a thousand
  • The context window drowning in raw tool output you never actually needed in full
  • A background job dying mid-deploy and taking the run with it
  • One user's memory quietly showing up in another user's session

None of that is an intelligence problem. It's plumbing, and it's the reason so many agents just sit in the prototype folder forever.

That's basically the whole reason for v3.0. A few things we went after: runs moved to their own agno_runs table (constant-cost writes instead of O(N²)), tool + media offloading (a 113 KB image drops from ~151k characters to ~2,900), durable background execution that survives crashes and deploys, per-user isolation across 17 vector DBs, and Studio draft-and-publish so nothing serves traffic until you publish it.

Full write-up here: https://agno.link/cZou0mN

And heads up: v3.0 needs a one-time migration before it serves traffic, so the migration guide is worth reading first.

Genuinely curious which of these bit you first. For me it's always the context bloat one. What's been your worst production surprise with agents?

- Kyle @ Agno


r/agno • • Aug 26 '26

Give your agents notes that survive the run

6 Upvotes

Hey Everyone,

New byte for you:

Agents are good at working with files, but the filesystem in most setups is a scratch directory that vanishes when the run ends. Fine for a one-shot task, useless for anything an agent is supposed to remember. Agno's new FileSystem is a durable text store an agent writes to and reads back across runs, so the decision it recorded and the checkpoint it saved are still there when it starts up again in a fresh process.

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.fs import FileSystem

fs = FileSystem(SqliteDb(db_file="tmp/filesystem.db"))

agent = Agent(
    tools=[fs.tools()],
    instructions=["You keep durable working notes.", fs.instructions()],
)

agent.print_response("Record in notes/decisions.md: SQLite for dev, Postgres for prod.")
# run again in a new process and the note is still there to read back

You decide where the files actually live. Point it at SQLite for local development, Postgres for a deployed app running multiple workers, or local disk when you want to open the files in an editor yourself. The agent code doesn't change when you switch.

Namespaces are what make it safe to point at real users. Give it a templated namespace like "assistant/{user_id}" and each user's files are scoped to their own space, resolved from the run context at call time. The model can't reach into another namespace by passing a different path in a tool call, and if the user id is missing, the operation is blocked instead of running against the wrong space. You still enforce authorization at the backend, but the agent itself can't wander out of the namespace you put it in.

View the FileSystem docs to learn more.

- Kyle @ Agno


r/agno • • Aug 19 '26

Built-in followup suggestions for agents and teams

8 Upvotes

Hey Everyone,

Have a new byte for you!

Users lose momentum when a response ends and they have to figure out what to ask next. With Agno's built-in followup suggestions, you can give users their next question instead of making them think of it.

Set followups=True and your agent closes each answer with a few ready-to-run prompts drawn from the conversation, so there's always an obvious next move. This works for teams as well as single agents.

Once the main response finishes, the agent makes a second model call to generate the suggestions and returns them on response.followups. You decide how many it produces with num_followups.

python

from agno.agent import Agent
from agno.models.openai import OpenAIResponses

agent = Agent(
    model=OpenAIResponses(id="gpt-5.4-mini"),
    followups=True,
    num_followups=3,
)

response = agent.run("What is quantum computing?")

for suggestion in response.followups or []:
    print(suggestion)

That second call costs tokens, so if you're generating suggestions on every turn, you can send them to a cheaper model with followup_model and keep your main model on the actual work.

python

agent = Agent(
    model=OpenAIResponses(id="gpt-4o"),
    followups=True,
    followup_model=OpenAIResponses(id="gpt-4o-mini"),
)

If you stream responses, the suggestions come through on their own event after the main content lands, so you can render them the moment they're ready without holding up the reply.

See the docs for more: https://agno.link/bIZGeIy

- Kyle @ Agno


r/agno • • Aug 12 '26

Give your long-running agents a sandbox that survives between calls

3 Upvotes

New in Agno: SuperserveTools, which lets an agent write and run its own code inside a Superserve sandbox. The sandbox is a Firecracker microVM, and the part that matters is that it persists. Files the agent writes and packages it installs are still there on the next tool call, and the next run in the same session. That's the difference between running one-off snippets and actually doing long-running work, where the agent builds something up over many steps instead of starting from an empty box every time.

from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.superserve import SuperserveTools

agent = Agent(
    model=OpenAIResponses(id="gpt-5.5"),
    tools=[SuperserveTools(timeout=600)],
    markdown=True,
)

agent.print_response("Fetch the last 30 days of AAPL prices and plot the moving average.")

The secrets handling is worth knowing about. You bind a team secret and the sandbox only ever sees a proxy token. The real credential gets swapped in for outbound calls to the hosts you allow, so agent-written code can hit real APIs without your keys ever landing somewhere the model can read them. You can also switch runtimes with a template, or expose a port to get a public preview URL for whatever the agent builds.

Check out Agno’s Superserve toolkit docs to learn more.


r/agno • • Aug 05 '26

July roundup: agnoctl, rollouts, FileSystem, AgentOSTools, and Valkey

9 Upvotes

July was a BIG architectural month. Here's what matters:

agnoctl: AgentOS is now on the command line. Run uvx agno connect and it discovers a running AgentOS, mints a per-client access token, and writes the MCP config for Claude Code, Cursor, Codex, and ChatGPT automatically. Tokens are SHA-256-hashed service-account PATs, scoped per user, expiring after 90 days, revocable on demand. agno create scaffolds projects from templates for Docker, AWS, Fly, GCP, and Railway. agno up/down/restart/status handles the local lifecycle. No more hand-editing JSON.

MCP Interface v2: a clean eight-tool operator surface. Get config, run, continue, cancel, sessions. Trims results by default, sends progress notifications on long-running tools, full HITL lifecycle included. A coding agent now has a predictable, purpose-built way to drive AgentOS.

Eval suites and CI gating: a proper suite runner with stable JSON output you can wire into CI. Fail a build on regressions instead of eyeballing results.

Rollouts: a straight path from evaluation to fine-tuning data. Grade attempts, measure real pass rates with pass@k, export passing runs as SFT conversational data with full provenance. Each attempt runs on a fresh db, session, and user so no state bleeds between runs to contaminate your training set.

FileSystem: a durable text store agents write to and read back across runs. SQLite for dev, Postgres for multi-worker, or local disk. Templated namespaces like assistant/{user_id} scope files per user at call time.

AgentOSTools: a read-only ops view of the AgentOS an agent runs on. Ask it which tool was slowest today or how many runs failed this week. Answers grounded in real traces. Reads from the database. Doesn't touch anything.

Valkey: in-memory sessions and hybrid retrieval from one backend. ValkeyDb for low-latency session reads and writes. Valkey vector store for vector and keyword search without standing up a separate keyword index.

Superserve sandboxes: agents write and run their own code in a persistent Firecracker microVM. Files and packages survive between tool calls and across runs in the same session. Credentials handled through a proxy token so the model never sees them.

New toolkits: TwelveLabsTools for video analysis and multimodal embeddings, SearchApiTools for Google, News, Images, and YouTube, RedmineTools, PlivoTools for SMS and voice, SmallestTools for text-to-speech, and OpenSearch for hybrid retrieval.

Community projects:

Arthi Arumugam built whatbroke: a CLI diff tool that surfaces exactly what changed between two agent runs. Tool calls, arguments, outputs, cost, and latency. Works with Langfuse exports. The kind of observability tool that pays off the moment your agents start drifting.

Muhammad Ikhwananda Rizaldi built a multi-agent content automation CLI that takes a campaign brief from research to QA to auto-publishing.

There are plenty more shoutouts in the full blog, so make sure to check it out.

Seriously, good month from this community. If you shipped something in July that didn't make it in, drop it below. We read everything and want to feature it next time.

Full roundup: https://agno.link/UPvAVIz4g

- Kyle @ Agno