Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c61cd27
docs: retarget sync tooling to Agno v2.7.4
ashpreetbedi Jul 19, 2026
56afee5
docs: sync examples to Agno v2.7.4
ashpreetbedi Jul 19, 2026
689c5ce
docs: align SDK references with Agno v2.7.4
ashpreetbedi Jul 19, 2026
a9bd431
docs: correct companion runtime and deployment claims
ashpreetbedi Jul 19, 2026
64fb1bd
docs: realign Demo OS guides with current sources
ashpreetbedi Jul 19, 2026
db71df3
docs: keep Modal log command generation current
ashpreetbedi Jul 19, 2026
09d17b5
docs: close source-backed security and runtime gaps
ashpreetbedi Jul 19, 2026
79f4b23
docs: include setup skill in deployment guides
ashpreetbedi Jul 19, 2026
c692aaf
docs: close convergence accuracy gaps
ashpreetbedi Jul 19, 2026
fe0f018
docs: enrich incomplete OpenAPI responses
ashpreetbedi Jul 19, 2026
e6c1ef7
docs: stabilize remote example titles
ashpreetbedi Jul 19, 2026
176204b
docs: repair stale generated example guidance
ashpreetbedi Jul 19, 2026
078511a
docs: align OpenAPI with v2.7.4 runtime branches
ashpreetbedi Jul 19, 2026
cada37b
docs: fix deployment reference snippets
ashpreetbedi Jul 19, 2026
13264a1
docs: close final source accuracy gaps
ashpreetbedi Jul 19, 2026
6812354
docs: correct runnable example guidance
ashpreetbedi Jul 19, 2026
d220832
docs: complete v2.7.4 interface contracts
ashpreetbedi Jul 19, 2026
41b2113
docs: close convergence contract gaps
ashpreetbedi Jul 19, 2026
7b4ec1c
docs: resolve final convergence findings
ashpreetbedi Jul 19, 2026
cfd3de0
docs: finalize team continuation contract
ashpreetbedi Jul 19, 2026
a9e0fc4
docs: complete continuation response contracts
ashpreetbedi Jul 19, 2026
d26a3a0
docs: harden filtering and runnable setup
ashpreetbedi Jul 19, 2026
621af53
docs: complete remaining API contracts
ashpreetbedi Jul 19, 2026
a9544a0
docs: correct agent platform skill count
ashpreetbedi Jul 19, 2026
ca5c559
docs: align Dash learning guarantees
ashpreetbedi Jul 19, 2026
8ba1051
docs: repair runnable client examples
ashpreetbedi Jul 19, 2026
bc78221
docs: complete local database setup
ashpreetbedi Jul 19, 2026
3229713
docs: harden generated runnable examples
ashpreetbedi Jul 19, 2026
33ac795
docs: correct released API edge cases
ashpreetbedi Jul 19, 2026
5191709
docs: correct generated import prerequisites
ashpreetbedi Jul 19, 2026
daebe29
docs: prepare repository assets for knowledge examples
ashpreetbedi Jul 19, 2026
a3d29bb
docs: repair authorization and learning quickstarts
ashpreetbedi Jul 19, 2026
07c4e81
docs: clarify database access boundaries
ashpreetbedi Jul 19, 2026
6b8279f
docs: correct MCP authentication boundaries
ashpreetbedi Jul 19, 2026
420ad30
docs: resolve final v2.7.4 audit findings
ashpreetbedi Jul 19, 2026
b693af9
docs: finish v2.7.4 source-backed repairs
ashpreetbedi Jul 19, 2026
d29d9ae
docs: close final v2.7.4 convergence gaps
ashpreetbedi Jul 19, 2026
713a73e
docs: close final v2.7.4 audit gaps
ashpreetbedi Jul 19, 2026
78b715f
docs: correct Agent Platform skill counts
ashpreetbedi Jul 19, 2026
f23d30d
docs: pin Agno implementation links to v2.7.4
ashpreetbedi Jul 19, 2026
c0f1072
docs: correct final v2.7.4 runtime mismatches
ashpreetbedi Jul 19, 2026
f3187eb
docs: fix v2.7.4 convergence findings
ashpreetbedi Jul 19, 2026
e5a2ca9
docs: add Anthropic setup to agent tutorial
ashpreetbedi Jul 19, 2026
dde9c49
docs: correct Slack session ID format
ashpreetbedi Jul 19, 2026
28fe006
docs: fix final runnable example defects
ashpreetbedi Jul 19, 2026
1dfa30f
docs: fix Dash deployment and connection steps
ashpreetbedi Jul 19, 2026
e4ff38a
docs: make A2A client examples runnable
ashpreetbedi Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion _snippets/chunking-document.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| `chunk_size` | `int` | `5000` | The maximum size of each chunk. |
| `chunk_size` | `int` | `5000` | Target size before overlap. A single long sentence or added overlap can produce a larger chunk. |
| `overlap` | `int` | `0` | The number of characters to overlap between chunks. |
43 changes: 32 additions & 11 deletions agent-os/client/a2a-client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,63 @@ asyncio.run(main())
Google ADK uses JSON-RPC mode:

```python
import asyncio

from agno.client.a2a import A2AClient

client = A2AClient("http://localhost:8001/", protocol="json-rpc")
result = await client.send_message(message="Hello!")

async def main():
client = A2AClient("http://localhost:8001/", protocol="json-rpc")
result = await client.send_message(message="Hello!")
print(result.content)


asyncio.run(main())
```

## Streaming Responses

Stream responses in real-time:

```python
import asyncio

from agno.client.a2a import A2AClient

client = A2AClient("http://localhost:7003/a2a/agents/my-agent")

async for event in client.stream_message(message="Tell me a story"):
if event.is_content and event.content:
print(event.content, end="", flush=True)
async def main():
client = A2AClient("http://localhost:7003/a2a/agents/my-agent")
async for event in client.stream_message(message="Tell me a story"):
if event.is_content and event.content:
print(event.content, end="", flush=True)


asyncio.run(main())
```

## Authentication

AgentOS instances running with `authorization=True` require a JWT on every A2A request. Pass it via `headers`:

```python
import asyncio
import os

from agno.client.a2a import A2AClient

client = A2AClient("https://my-agent-os.com/a2a/agents/my-agent")
headers = {"Authorization": f"Bearer {os.environ['AGENT_OS_JWT']}"}

result = await client.send_message(message="Hello!", headers=headers)
async def main():
client = A2AClient("https://my-agent-os.com/a2a/agents/my-agent")
headers = {"Authorization": f"Bearer {os.environ['AGENT_OS_JWT']}"}

async for event in client.stream_message(message="Hello!", headers=headers):
...
result = await client.send_message(message="Hello!", headers=headers)
print(result.content)

async for event in client.stream_message(message="Hello!", headers=headers):
...


asyncio.run(main())
```

`send_message`, `stream_message`, and `get_agent_card` all accept `headers`. The token needs the target's run scope (`agents:run`, or per-resource `agents:my-agent:run`) for `message:send` and `message:stream`. See [Scopes](/agent-os/security/authorization/scopes) for the full mapping.
Expand Down
4 changes: 2 additions & 2 deletions agent-os/connect-your-os.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: "Connect your AgentOS to the control plane for monitoring and manag
## Connect Your AgentOS

1. Open [os.agno.com](https://os.agno.com) and sign in
2. Click **"Add new OS"**
2. Click **Connect OS**

<Frame>
<video
Expand Down Expand Up @@ -38,4 +38,4 @@ Click **"CONNECT"**. If successful, your OS appears in the dashboard.
|-----------|----------|
| Status | "Running" |
| Features | Chat, Knowledge, Memory, Sessions accessible |
| Agents | Configured agents appear in the chat interface |
| Agents | Configured agents appear in the chat interface |
2 changes: 1 addition & 1 deletion agent-os/factories/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Use a plain `Agent` / `Team` / `Workflow` when the component is shared across al
`GET /agents/{id}`, `GET /teams/{id}`, and `GET /workflows/{id}` (the component-detail endpoints) return the factory's metadata without invoking it. See the [Factories reference](/reference/agent-os/factories) for per-endpoint behavior and discovery payload shape.
</Note>

## Learn How To
## Guides

<CardGroup cols={3}>
<Card title="AgentFactory" icon="user" href="/agent-os/factories/agent-factory">
Expand Down
4 changes: 2 additions & 2 deletions agent-os/interfaces/ag-ui/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ With Dojo running, open `http://localhost:3000` and select the Agno agent.
</Step>
</Steps>

Additional examples are available in the [cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/05_agent_os/interfaces/agui/).
Additional examples are available in the [cookbook](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/05_agent_os/interfaces/agui/).

## Custom Events

Expand Down Expand Up @@ -156,4 +156,4 @@ Use `AgentOS.serve` to run the app with Uvicorn.
| `workers` | `Optional[int]` | `None` | Number of Uvicorn worker processes. |
| `access_log` | `bool` | `False` | Enable Uvicorn access logging. |

See [cookbook examples](https://github.com/agno-agi/agno/tree/main/cookbook/05_agent_os/interfaces/agui/) for updated interface patterns.
See [cookbook examples](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/05_agent_os/interfaces/agui/) for updated interface patterns.
2 changes: 1 addition & 1 deletion agent-os/interfaces/slack/features.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ agent = Agent(
Each Slack thread maps to one session. DMs work the same way. All responses are sent as thread replies, keeping channel conversations organized. Conversations persist across server restarts.

<Note>
Session format: `{entity_id}:{thread_ts}`. For example, an agent named "Support Bot" gets the auto-generated ID `support-bot` and produces session IDs like `support-bot:1719000000.000100`.
New session format: `{entity_id}:{channel_id}:{thread_ts}`. For example, an agent named "Support Bot" with channel ID `C012345` produces session IDs like `support-bot:C012345:1719000000.000100`. The interface reuses an existing `{entity_id}:{thread_ts}` session when it finds one from an earlier version.
</Note>

## Files
Expand Down
2 changes: 1 addition & 1 deletion agent-os/interfaces/slack/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Create a Slack app for your agent and configure the permissions and events it ne

The manifest is the quickest setup path. It pre-configures the scopes, events, and settings needed for DMs, @mentions, and [Human-in-the-Loop](/hitl/overview) interactions.

1. Download [manifest.json](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/os/interfaces/slack/manifest.json) and replace `https://YOUR-URL` with your ngrok URL
1. Download [manifest.json](https://github.com/agno-agi/agno/blob/v2.7.4/libs/agno/agno/os/interfaces/slack/manifest.json) and replace `https://YOUR-URL` with your ngrok URL
2. Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → **From a manifest**
3. Select your workspace, choose **JSON**, and paste the manifest contents
4. Click **Next**, review the summary, then click **Create**
Expand Down
2 changes: 1 addition & 1 deletion agent-os/interfaces/whatsapp/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ agent = Agent(
)
```

See the [interactive concierge example](https://github.com/agno-agi/agno/blob/main/cookbook/05_agent_os/interfaces/whatsapp/interactive_concierge.py) for a full agent using all interactive features.
See the [interactive concierge example](https://github.com/agno-agi/agno/blob/v2.7.4/cookbook/05_agent_os/interfaces/whatsapp/interactive_concierge.py) for a full agent using all interactive features.

For parameters and methods, see the [WhatsAppTools reference](/tools/toolkits/social/whatsapp).

Expand Down
44 changes: 26 additions & 18 deletions agent-os/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ sidebarTitle: "Introduction"
description: "The runtime for your agent platform."
---

**AgentOS is a FastAPI app that turns your agents into a platform.** It's a backend service that:
**AgentOS is a FastAPI app that turns your agents into a platform.** The backend service:

1. Runs agents via REST API, MCP, or interfaces like Slack, WhatsApp and Telegram.
2. Maintains long-running stateful sessions that last from minutes to days to weeks.
3. Is durable across restarts, replicas, and infrastructure failures.
4. Is secure against unauthenticated access.
5. Logs, traces and audits every run and action.
2. Stores sessions, memory, knowledge, and traces in your configured databases.
3. Preserves database-backed state across restarts and replicas when all instances use the same persistent stores.
4. Supports JWT authorization, service account tokens, and security-key authentication.
5. Supports database-backed tracing for agents, teams, and workflows.

Build your agents using the [Agno SDK](/sdk/introduction). Run them using the AgentOS runtime.

Here's the smallest possible AgentOS:
A minimal AgentOS:

```python agno_assist.py
from agno.agent import Agent
Expand All @@ -32,14 +32,18 @@ agent_os = AgentOS(agents=[agent])
app = agent_os.get_app()
```

<Warning>
Authorization and tracing are disabled by default. Telemetry is enabled by default. Configure authentication before exposing AgentOS, and review [Agno telemetry](/telemetry) before deployment.
</Warning>

## Key Features

- **Production API**: 50+ ready to use endpoints with SSE-compatible streaming.
- **Data Ownership**: Sessions, memory, knowledge, and traces stored in your database.
- **Request Isolation**: No state bleed between users, agents, or sessions.
- **Security**: JWT-based RBAC with hierarchical scopes.
- **Observability**: Traces stored in your database with no third-party egress or vendor lock-in.
- **Governance**: Guardrails, human-in-the-loop, and approval flows for full control.
- **Data Ownership**: Sessions, memory, knowledge, and traces stored in your configured databases.
- **Request Context**: User and session IDs scope persisted runs. JWT user isolation can bind these IDs to authenticated callers.
- **Security**: Optional JWT-based RBAC with hierarchical scopes, service account tokens, or a shared security key.
- **Observability**: Optional traces stored in your database.
- **Governance**: Guardrails, human-in-the-loop, and approval flows.
- **Multi-framework**: Serve agents built with the Claude Agent SDK, LangGraph and DSPy alongside native Agno agents. See [Multi-Framework Support](/agent-os/multi-framework/overview).

## Architecture
Expand All @@ -63,20 +67,24 @@ The runtime exposes the APIs that power both the control plane and your AI produ
alt="AgentOS Architecture"
/>

## Private by Design
## Data Flow and Storage

The AgentOS runtime runs in your infrastructure. Sessions, memory, knowledge, and enabled traces are stored in your configured databases. The [control plane](/agent-os/control-plane) connects from your browser to the runtime.

Most AI tooling stores your data on their servers. You pay retention costs, deal with egress fees, and depend on their security. AgentOS runs entirely in your infrastructure: the runtime runs as a container in your cloud, and the [control plane](/agent-os/control-plane) connects directly from your browser. No proxies. No data relays.
Network traffic depends on your configuration:

- **Your database**: Sessions, memory, knowledge, traces. All stored where you control it.
- **Zero transmission**: No conversations, logs, or metrics sent to Agno.
- **From browser to runtime**: The control plane connects from your browser to the runtime. Agno stores no data except for your runtime endpoint. All data resides in your database.
| Destination | Data |
|-------------|------|
| Configured model and tool providers | Requests required by those providers and tools |
| `https://os-api.agno.com` | Usage metadata when telemetry is enabled. Prompts and responses are excluded. |
| Your AgentOS runtime | Control plane requests sent directly from the browser |

See [AgentOS Security](/agent-os/security/overview) for more details.
AgentOS telemetry is enabled by default. Set `telemetry=False` on `AgentOS` to disable its launch event. Agents, teams, workflows, and evals have separate telemetry controls. See [Agno telemetry](/telemetry) for payload details and [AgentOS Security](/agent-os/security/overview) for authentication options.

<Frame>
<img
src="/images/agentos-secure-infra-illustration.png"
alt="AgentOS Security and Privacy Architecture"
alt="AgentOS runtime and control plane connections"
style={{ borderRadius: "0.5rem" }}
/>
</Frame>
Expand Down
2 changes: 1 addition & 1 deletion agent-os/learnings/manage-learnings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ AgentOS exposes `/learnings` REST endpoints for CRUD over the `agno_learnings` t

## Prerequisites

- A supported database: PostgreSQL, SQLite, or MongoDB. Other databases return `501`.
- A database backend that implements learning CRUD. Backends without those methods, including `RemoteDb`, return `501`.
- An agent with learning enabled (see the [Learning quickstart](/learning/quickstart)).

## Example
Expand Down
11 changes: 7 additions & 4 deletions agent-os/mcp/mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,23 +154,26 @@ Combine `tools=[...]` with `enable_builtin_tools=False` to expose a single purpo

## Authentication

Authentication is enforced on `/mcp` in every mode. One auth layer covers the REST routes and the MCP server: any credential that works against the API works against `/mcp`, passed as a Bearer token.
When `mcp_auth` is unset, `/mcp` follows the parent AgentOS authentication mode. JWT and security-key modes require bearer credentials. The `none` mode permits anonymous MCP requests. When `mcp_auth` is set, the configured FastMCP provider protects the mounted app and the parent middleware exempts its OAuth paths.

| Mode | Server setup | Client credential |
|------|--------------|-------------------|
| Security key | `export OS_SECURITY_KEY="your-key"` | `Authorization: Bearer <security key>` |
| Service account token | Issue via `POST /service-accounts` (requires a database) | `Authorization: Bearer agno_pat_...` |
| JWT | `AgentOS(authorization=True, ...)` | `Authorization: Bearer <JWT>` |
| MCP OAuth | `AgentOS(mcp_auth=...)` | Credential accepted by the configured FastMCP provider |
| Open | No JWT source, security key, or `mcp_auth` | No credential required |

When the parent authentication layer is active and database-backed verification is available, it also accepts valid service account tokens and enforces their scopes. A database alone does not activate authentication on an otherwise open `none` deployment. On that open `/mcp` endpoint, bearer values are ignored and the request remains anonymous.

With `authorization=True`, each tool call is checked against the scopes of its equivalent REST route: `run_agent` requires the same scopes as `POST /agents/{id}/runs`, `get_sessions` the same as `GET /sessions`. See [Security & Auth](/agent-os/security/overview).

The `authorize` gate on `MCPServerConfig` layers on top of authentication: it receives the verified `user_id` and can reject callers per request. Without `authorization=True` no JWT layer resolves the caller, so the gate is called with `user_id=None`. Make sure your gate handles `None`, and return `False` if you want to reject unauthenticated callers.
The `authorize` gate on `MCPServerConfig` runs after the configured authentication path. It receives the caller's `user_id` when parent authentication, MCP OAuth, or a valid service account token establishes one. On an open endpoint, anonymous calls pass `user_id=None`. Make sure your gate handles `None`, and return `False` to reject unauthenticated callers.

## Transport Security

fastmcp's built-in Host/Origin guard is disabled on `/mcp`, so `MCPServerConfig.allowed_hosts` acts as the transport guard instead:

- Left unset, the default depends on your auth mode. A server with authentication (a security key or JWT) skips host validation, because every request already has to prove itself. An open server gets localhost-only validation, since that is exactly the setup DNS rebinding attacks target.
- Left unset, the default depends on your auth mode. A server with authentication (a security key, JWT, or MCP OAuth) skips host validation, because every request already has to prove itself. An open server gets localhost-only validation, since that is exactly the setup DNS rebinding attacks target.
- When set, the request `Host` (and `Origin`, when present) must match your list or the localhost defaults (`localhost`, `127.0.0.1`, `[::1]`). Anything else is rejected with 400 before it reaches the MCP machinery. `*.example.com` wildcard patterns are supported.

This is DNS-rebinding protection: it stops a malicious web page from driving an always-on local MCP server through a rebound DNS name. List only your deploy or tunnel host; localhost works out of the box.
Expand Down
4 changes: 2 additions & 2 deletions agent-os/middleware/custom.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ Error responses must be returned as `JSONResponse` objects to ensure proper seri
```python custom_middleware.py
from agno.os import AgentOS
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses

db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
db = SqliteDb(db_file="tmp/agent.db")

agent = Agent(
name="Basic Agent",
Expand Down
8 changes: 5 additions & 3 deletions agent-os/middleware/jwt.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Auth Middleware
sidebarTitle: JWT
description: Configure AuthMiddleware for JWT validation, claim injection, and RBAC across REST, MCP, and WebSocket connections.
description: Configure AuthMiddleware for JWT validation, claim injection, and RBAC on AgentOS routes.
keywords: [jwt middleware, auth middleware, jwt authentication, token validation, parameter injection, authorization, bearer token, jwt claims, http only cookies, token verification, jwt secret, user authentication, session management, jwt tokens, pyjwt, token security, rbac, scopes, role-based access control, service accounts]
---

Expand Down Expand Up @@ -39,14 +39,16 @@ app.add_middleware(

## Coverage Across Surfaces

AgentOS installs a single `AuthMiddleware` instance on the parent app in every authenticated deployment mode. A token accepted on one surface is accepted with identical constraints on the others.
AgentOS installs `AuthMiddleware` on the parent app when the parent authentication mode uses JWTs or a security key. When a database verifier is available, that same layer also accepts service account tokens. Credentials share identical constraints only across surfaces handled by the middleware.

| Surface | How it is covered |
|---------|-------------------|
| REST routes | Requests pass through the middleware directly |
| Mounted `/mcp` app | Parent-app middleware runs before the mount dispatches, so the MCP server carries no auth code of its own |
| Mounted `/mcp` app | Parent middleware covers the mount when `mcp_auth` is unset. With `AgentOS(mcp_auth=...)`, the parent exempts the MCP OAuth paths and the FastMCP provider authenticates inside the mounted app. |
| WebSockets | The middleware publishes its validator, audience, admin scope, and user-isolation settings to `app.state`; WebSocket handshakes validate against the same configuration |

Self-authenticating webhook interfaces verify their own inbound requests and are excluded from the parent layer.

### Credential Dispatch

The middleware resolves each bearer credential in order:
Expand Down
4 changes: 2 additions & 2 deletions agent-os/middleware/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ Add middleware to the FastAPI app returned by `get_app()`:
```python agent_os.py
from agno.os import AgentOS
from agno.os.middleware.jwt import AuthMiddleware
from agno.db.postgres import PostgresDb
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.agent import Agent

db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
db = SqliteDb(db_file="tmp/agent.db")

agent = Agent(
name="Basic Agent",
Expand Down
Loading
Loading