This guide is for the engineers, architects, and operators who run Agno in production: people standing up an AgentOS service, wiring it to a database, securing it with JWT and RBAC, instrumenting it with tracing, and deploying it to a cloud. It documents the system's architecture, the monorepo layout, the full configuration surface, the storage and security models, operational procedures, and the internals you need to extend or debug the framework.
For end-user, task-oriented material — building agents, adding tools, writing workflows — see the companion User Guide. This guide assumes you have read it and focuses on running Agno as a platform.
Source of truth. Everything here is derived from the Agno source at commit
5b9cfec(package version2.6.12). Where behavior depends on a constructor flag or environment variable, the exact name from the source is given.
1. Executive Summary
Agno is a Python SDK — distributed as the agno package — for building agent platforms. It is not a hosted service: you embed it in your own code and run it on your own infrastructure, against your own database. There is no required Agno-operated backend; the optional os.agno.com control plane is a UI that talks to your AgentOS instance.
The system has three layers, each opt-in:
| Layer | What it is | When you need it |
|---|---|---|
Core SDK (agno) |
The Agent, Team, Workflow primitives plus models, tools, knowledge, memory, and DB adapters. |
Always. |
AgentOS (agno[os]) |
A FastAPI runtime that exposes your agents as a REST API with auth, tracing, scheduling, and chat interfaces. | When serving agents over HTTP or to a product. |
Infra (agno-infra / the ag CLI) |
Scaffolding and deployment tooling for Docker and AWS. | When deploying AgentOS to a cloud. |
Architecturally significant properties:
- Stateless compute, stateful database. Agents themselves hold no durable state. Sessions, user memories, knowledge, traces, and component definitions all live in a database you supply (
db=). This makes AgentOS horizontally scalable — run many replicas behind a load balancer, all pointed at the same DB. - Provider-agnostic. 50+ model providers sit behind a single
Modelinterface; switching providers is a one-line change. - Dependency-light core, heavy optional surface. The core depends only on
pydantic,httpx,typer,rich,pyyaml, and a few others. Every model, tool, vector DB, and storage backend is an optional extra, so a production image installs only what it uses.
2. Architecture
2.1 Request lifecycle
When a client calls an AgentOS run endpoint (e.g. POST /agents/{id}/runs), the flow is:
HTTP request
│
▼
FastAPI route (os/routers/agents)
│ ── JWT/auth middleware: validate token, resolve scopes ──┐
│ │ (RBAC)
▼ │
Resolve Agent by id (from registered agents or DB) │
│ │
▼ │
Agent.arun(input, session_id, user_id) │
│ 1. Load session + history from db │
│ 2. Build context (system msg, history, knowledge, memory)│
│ 3. Resolve tools (incl. MCP, callable factories) │
│ 4. Call Model ◄──► tool-call loop ──► provider API │
│ 5. Optional: reasoning, guardrails (pre/post hooks) │
│ 6. Persist run, update memory/summaries (async) │
│ 7. Emit OpenTelemetry trace span (if tracing=True) │
▼ │
RunOutput ── serialized to JSON or streamed via SSE ──────────┘
The agent's logic is intentionally split across private submodules under agno/agent/ — _run.py (the run loop), _messages.py (context building), _tools.py (tool resolution), _session.py (persistence), _managers.py (memory/culture). The public agent.py is a thin dataclass plus a facade that delegates to these. When debugging the run loop, read agno/agent/_run.py, not agent.py.
2.2 The core primitives
| Primitive | Module | Role |
|---|---|---|
Agent |
agno/agent/agent.py |
One model + context + tools. The atomic unit of work. |
Team |
agno/team/team.py |
A leader model coordinating member agents/teams in one of four modes. |
Workflow |
agno/workflow/workflow.py |
A deterministic step graph (Step, Parallel, Loop, Condition, Router). |
Model |
agno/models/base.py + agno/models/<provider>/ |
Provider adapter; uniform interface over chat/completions APIs. |
Toolkit |
agno/tools/toolkit.py |
A named bundle of callable tools. |
Knowledge |
agno/knowledge/knowledge.py |
RAG layer: readers → chunkers → embedders → vector DB → reranker. |
AgentOS |
agno/os/app.py |
FastAPI app that wires primitives to HTTP. |
2.3 The database as the system of record
Every durable concern routes through a BaseDb implementation (agno/db/base.py). One database can hold all component types: sessions, runs, user memories, session summaries, knowledge metadata, traces, eval runs, and saved component definitions (versioned agents/teams/workflows). The ComponentType and SessionType enums in agno/db/base.py classify what is stored.
This single-DB design is why AgentOS(db=...) can auto-provision tables (auto_provision_dbs=True by default) and why agents declared without their own db inherit the OS-level one.
3. Repository Layout (Monorepo)
Agno is a monorepo. Operators should understand which package provides what.
agno/ (repository root)
├── libs/
│ ├── agno/ → the `agno` PyPI package (the SDK)
│ │ ├── agno/
│ │ │ ├── agent/ Agent class + private run/message/tool/session modules
│ │ │ ├── team/ Team class + coordination modes
│ │ │ ├── workflow/ Workflow + Step/Parallel/Loop/Condition/Router
│ │ │ ├── models/ 50+ provider adapters (openai, anthropic, google, …)
│ │ │ ├── tools/ ~130 toolkits + @tool decorator + Toolkit base
│ │ │ ├── knowledge/ readers, chunking, embedders, rerankers
│ │ │ ├── vectordb/ pgvector, lancedb, chroma, qdrant, milvus, …
│ │ │ ├── db/ postgres, sqlite, mysql, mongo, redis, dynamo, …
│ │ │ ├── memory/ user-memory managers + strategies
│ │ │ ├── session/ session + summary objects
│ │ │ ├── os/ AgentOS: app.py, routers/, middleware/, auth, scopes
│ │ │ ├── reasoning/ step-by-step reasoning
│ │ │ ├── guardrails/ input/output guardrails
│ │ │ ├── scheduler/ cron scheduling
│ │ │ ├── tracing/ OpenTelemetry spans + schemas
│ │ │ └── registry/ component registry
│ │ ├── migrations/ v1→v2 migration helpers
│ │ └── pyproject.toml package metadata + ALL optional extras
│ └── agno_infra/ → the `agno-infra` package (the `ag` CLI)
│ └── agno/
│ ├── cli/ entrypoint + `infra` subcommands
│ ├── docker/ Docker resource definitions
│ └── aws/ AWS resource definitions (ECS, RDS, S3, …)
├── cookbook/ hundreds of runnable examples (not shipped)
└── scripts/ dev/release scripts
Note
cookbook/is the single best onboarding resource — every feature has a runnable example there, organized by topic (02_agents,03_teams,04_workflows,05_agent_os,07_knowledge,91_tools,90_models). It is not part of the installed package.
4. Requirements
| Requirement | Detail |
|---|---|
| Python | 3.9+ (metadata says 3.7+, but 3.9 is the realistic floor). |
| Core dependencies | pydantic, pydantic-settings, httpx[http2], typer, rich, pyyaml, python-dotenv, python-multipart, gitpython, packaging, docstring-parser, typing-extensions. |
| Model provider | At least one, installed as an extra (agno[openai], etc.) plus its API key. |
| AgentOS | agno[os] → fastapi[standard], uvicorn, sqlalchemy, PyJWT, opentelemetry-sdk, croniter, pytz. |
| Database (for persistence) | A backend extra: agno[postgres], agno[sqlite], agno[redis], etc. |
| Deployment (optional) | agno-infra, plus Docker and/or AWS credentials. |
Production images should pin Agno and install exactly the extras needed:
pip install "agno[os,postgres,pgvector,openai,anthropic]==2.6.12"
Warning
Some extras are intentionally disabled at the source level due to upstream supply-chain incidents (the
pyproject.tomlnoteslitellmcompromised on PyPI 2026-03-24 andmistralaiquarantined 2026-05-12, both excluded from the aggregateagno[models]extra). If you need those providers, install them deliberately and review their advisories first.
5. AgentOS: Configuration Mastery
AgentOS (agno/os/app.py) is the deployment unit. Its constructor is the primary configuration surface.
5.1 Constructor reference
from agno.os import AgentOS
agent_os = AgentOS(
agents=[...], teams=[...], workflows=[...], knowledge=[...],
db=...,
...
)
| Argument | Default | Purpose |
|---|---|---|
agents / teams / workflows / knowledge |
None |
The components to serve. At least one of these or db is required or the constructor raises ValueError. |
db |
None |
Default database. Components without their own db inherit it. |
id / name / description / version |
None |
Instance identity (shown in the home/registry endpoints). |
interfaces |
None |
Chat interfaces (Slack, Telegram, WhatsApp, Discord, AG-UI). |
a2a_interface |
False |
Expose agents/teams over the A2A (agent-to-agent) protocol. |
authorization |
False |
Enable JWT auth + RBAC middleware. See §7. |
authorization_config |
None |
Fine-tune the JWT middleware (admin scope, claim mapping). |
cors_allowed_origins |
None |
Extra CORS origins (merged with Agno defaults). |
config |
None |
Path to a YAML config file or an AgentOSConfig. |
settings |
None |
AgnoAPISettings instance (env-driven). |
lifespan |
None |
Custom FastAPI lifespan context manager. |
enable_mcp_server |
False |
Expose the OS itself as an MCP server. |
base_app |
None |
Mount AgentOS onto an existing FastAPI app. |
on_route_conflict |
"preserve_agentos" |
Conflict policy when using base_app: keep AgentOS routes, keep base-app routes, or error. |
tracing |
False |
Enable OpenTelemetry tracing for all agents/teams. |
auto_provision_dbs |
True |
Auto-create DB tables on startup. |
run_hooks_in_background |
False |
Run pre/post hooks as FastAPI background tasks (non-blocking). |
telemetry |
True |
Anonymous usage telemetry. Set False to disable. |
registry |
None |
Custom component registry. |
scheduler |
False |
Enable the cron scheduler. |
scheduler_poll_interval |
15 |
Seconds between scheduler polls. |
scheduler_base_url |
None |
Base URL for scheduler→OS HTTP calls (default http://127.0.0.1:7777). |
internal_service_token |
None |
Scheduler-to-OS auth token (auto-generated if unset). |
5.2 Getting and serving the app
app = agent_os.get_app() # returns the FastAPI instance (for uvicorn/gunicorn)
agent_os.serve("module:app", host="0.0.0.0", port=7777, workers=4)
serve() wraps uvicorn. Host and port can be overridden by environment variables (see below) — env wins over the arguments.
5.3 Environment variables
| Variable | Effect |
|---|---|
AGENT_OS_HOST |
Override the serve host. |
AGENT_OS_PORT |
Override the serve port. |
AGNO_API_RUNTIME |
stg points the control-plane link at os-stg.agno.com; otherwise os.agno.com. |
AGNO_TELEMETRY |
false disables usage telemetry. |
JWT_VERIFICATION_KEY |
Symmetric secret (HS*) for JWT validation. |
JWT_JWKS_FILE |
Path to a JWKS file for asymmetric (RS*) JWT validation. |
<PROVIDER>_API_KEY |
Model provider credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, …). |
5.4 AgnoAPISettings
The settings= argument takes an AgnoAPISettings (agno/os/settings.py), a pydantic-settings model populated from the environment:
| Field | Default | Purpose |
|---|---|---|
env |
"dev" |
Deployment environment label. |
docs_enabled |
True |
Serve /docs and /redoc. Set False in production to hide the OpenAPI UI. |
os_security_key |
None |
A static bearer token for simple API auth (alternative to full JWT). |
authorization_enabled |
False |
Set when JWT middleware is active. |
cors_origin_list |
Agno domains | Allowed CORS origins (Agno's own domains are always appended). |
Important
In production, either enable full JWT authorization (
authorization=True) or setos_security_keyto a strong secret. With neither, the API is unauthenticated. Also setdocs_enabled=Falseto avoid exposing your endpoint schema.
6. Storage Backends
All persistence goes through a BaseDb / AsyncBaseDb implementation. Pick the backend that matches your operational stack; the agent/OS code is identical regardless.
| Backend | Import | Extra | Notes |
|---|---|---|---|
| PostgreSQL | agno.db.postgres → PostgresDb / AsyncPostgresDb |
agno[postgres] / agno[async_postgres] |
Recommended default for production. |
| SQLite | agno.db.sqlite → SqliteDb / AsyncSqliteDb |
agno[sqlite] |
Great for local/dev and single-node. |
| MySQL | agno.db.mysql |
agno[mysql] |
|
| MongoDB | agno.db.mongo |
agno[async_mongo] |
Document store. |
| Redis | agno.db.redis |
agno[redis] |
Fast, ephemeral-friendly. |
| DynamoDB | agno.db.dynamo |
(AWS SDK) | Serverless on AWS. |
| Firestore / GCS-JSON | agno.db.firestore / agno.db.gcs_json |
GCP SDKs | GCP-native. |
| SingleStore | agno.db.singlestore |
agno[singlestore] |
|
| In-memory / JSON | agno.db.in_memory / agno.db.json |
— | Tests, demos. |
from agno.db.postgres import PostgresDb
db = PostgresDb(db_url="postgresql+psycopg://ai:ai@db:5432/agno")
6.1 Provisioning and migrations
- Auto-provisioning. With
auto_provision_dbs=True(default), AgentOS creates required tables on startup. - Migrations. Schema-evolution helpers live in
agno/db/migrations/(Alembic-styleversions/). Amigrations/v1_to_v2/package exists for upgrading data written by Agno v1 to the v2 schema. Run migrations as a deliberate, backed-up step in production; do not rely on auto-provisioning to alter existing tables.
6.2 Vector databases (for Knowledge)
Knowledge persistence is separate from the relational db. Supported vector stores include PgVector, LanceDb, Chroma, Qdrant, Milvus, Pinecone, Weaviate, MongoDb, Redis, Couchbase, Cassandra, SingleStore, Clickhouse, SurrealDb, and UpstashDb (each under agno/vectordb/<name> with a matching extra).
Tip
A common production topology is one Postgres instance serving both roles:
PostgresDbfor sessions/memory/traces andPgVector(same database,pgvectorextension) for knowledge. This minimizes operational surface.
7. Security
7.1 Authentication options
AgentOS offers two authentication models:
- Static bearer token — set
settings.os_security_key. Every request must sendAuthorization: Bearer <key>. Simple, coarse-grained (all-or-nothing). Suitable for internal/single-tenant deployments. - JWT + RBAC — set
authorization=True(or configure JWT env vars). The JWT middleware validates tokens and enforces per-resource scopes. Required for multi-user / multi-tenant deployments.
JWT validation is configured via environment:
| Variable | Use |
|---|---|
JWT_VERIFICATION_KEY |
Shared secret for symmetric (HS256/384/512) tokens. |
JWT_JWKS_FILE |
JWKS file path for asymmetric (RS*/ES*) tokens — point this at your IdP's published keys. |
The middleware extracts the bearer token from the Authorization header, validates the signature, and attaches the caller's scopes to the request for downstream authorization.
7.2 RBAC scopes
Authorization is scope-based (agno/os/scopes.py). Scopes come in three shapes:
| Shape | Example | Grants |
|---|---|---|
| Admin | agent_os:admin |
Full access to everything. |
| Global resource | agents:read, sessions:write |
An action on all resources of a type. |
| Per-resource | agents:web-agent:run |
An action on one specific resource. |
| Wildcard per-resource | agents:*:run |
An action on all resources of a type (explicit wildcard). |
Resource types include agents, teams, workflows, sessions, memories, knowledge, metrics, traces, schedules, approvals, and config. Legacy system:* scopes are accepted as aliases for config:*.
The middleware filters list endpoints to only the resources a token may see (get_accessible_resources, filter_resources_by_access) and gates run/mutation endpoints with check_resource_access / require_resource_access. Multi-tenant isolation is achieved by issuing each tenant a token scoped to their resource ids.
# A token granting run access to one agent and read access to its sessions:
scopes: ["agents:support-bot:run", "sessions:read"]
7.3 CORS and surface hardening
- CORS origins are controlled by
cors_allowed_origins/settings.cors_origin_list. Agno's own domains (agno.com,app.agno.com,os.agno.com,localhost:3000) are always appended so the hosted control-plane UI can connect; remove these inset_cors_origin_listif you do not use the Agno UI. - Disable the OpenAPI docs in production (
docs_enabled=False). - Run agents with least-privilege tools. Gate dangerous tools behind
@tool(requires_confirmation=True)and the approvals workflow (/approvalsendpoints) so a human resolves them before execution.
7.4 Secrets and credentials
Model and tool credentials are read from environment variables (python-dotenv loads a .env automatically). Never bake keys into images. Per the source's error surface, a missing key fails loudly at first use with ValueError: <PROVIDER>_API_KEY not set.
8. Observability & Tracing
Set tracing=True on AgentOS (or per agent) to emit OpenTelemetry spans for every run. Spans capture the model calls, tool calls, reasoning steps, and timings. Schemas live in agno/tracing/schemas.py, which imports opentelemetry-sdk at module load — so opentelemetry-sdk must be installed wherever tracing-capable routers are imported (it is part of agno[os]).
Traces are also queryable through the API:
| Endpoint | Purpose |
|---|---|
GET /traces |
List traces. |
GET /traces/{trace_id} |
One trace. |
POST /traces/search |
Search/filter traces. |
GET /traces/filter-schema |
Discover available filters. |
GET /trace_session_stats |
Aggregate stats. |
Run-level metrics (token counts, latencies) are on every RunOutput.metrics and exposed at GET /metrics (with POST /metrics/refresh to recompute). For third-party observability, cookbook/observability/ shows integrations with Langfuse, Langsmith, Arize Phoenix, Logfire, MLflow, and others via OpenInference — configured purely through their own env vars (e.g. LANGFUSE_PUBLIC_KEY, PHOENIX_API_KEY), not Agno-specific config.
9. Scheduling & Background Jobs
Enable the cron scheduler with scheduler=True. It polls every scheduler_poll_interval seconds (default 15) and triggers scheduled runs via HTTP back into the OS (scheduler_base_url, default http://127.0.0.1:7777), authenticated with internal_service_token. The scheduler needs croniter and pytz (agno[scheduler], also pulled by agno[os]).
Manage schedules through the API:
| Endpoint | Purpose |
|---|---|
GET /schedules, GET /schedules/{id} |
List / get. |
POST /schedules/{id}/enable / .../disable |
Toggle. |
POST /schedules/{id}/trigger |
Fire now. |
GET /schedules/{id}/runs |
Execution history. |
Note
The scheduler runs in-process with no external broker (no Celery/Redis queue required). For high-availability scheduling across replicas, ensure only one instance owns scheduling or coordinate via the shared DB; running the scheduler on every replica will multiply triggers.
10. Deployment
10.1 Running the server
AgentOS is a standard ASGI app. For production, run it under uvicorn/gunicorn with multiple workers behind a reverse proxy:
# directly
python my_os.py # calls agent_os.serve(..., workers=4)
# or via uvicorn
uvicorn my_os:app --host 0.0.0.0 --port 7777 --workers 4
Because compute is stateless, scale horizontally by running more replicas against the same database. Put TLS termination, rate limiting, and (optionally) auth at the proxy.
10.2 The ag CLI (agno-infra)
The agno-infra package provides the ag entrypoint (agno.cli.entrypoint:agno_cli) for scaffolding and deploying AgentOS to Docker or AWS:
| Command | Action |
|---|---|
ag infra create |
Scaffold a new AgentOS codebase (optionally from a template/URL). |
ag infra up |
Provision/start resources for the active codebase. |
ag infra down |
Tear down resources. |
ag infra patch |
Apply updates to running resources. |
ag infra restart |
Restart resources. |
ag infra config |
Print the active codebase's infra config. |
ag infra delete |
Remove the codebase's infra record. |
The AWS resource library (libs/agno_infra/agno/aws/resource/) covers ECS, EC2, RDS, ElastiCache, S3, IAM, ELB, ACM, Secrets Manager, Glue, EMR, and CloudFormation — i.e. it can stand up a full container-based deployment. The Docker resource library targets local/compose-style deployment.
10.3 Containerization
A typical Dockerfile installs only the needed extras and runs serve:
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install "agno[os,postgres,pgvector,openai]==2.6.12"
ENV AGENT_OS_HOST=0.0.0.0 AGENT_OS_PORT=7777 AGNO_TELEMETRY=false
EXPOSE 7777
CMD ["python", "my_os.py"]
Tip
Bake your provider API keys in at runtime (env/secret manager), not build time. Point
db_urlat a managed Postgres. Setauto_provision_dbs=Falseonce schema is stable and run migrations explicitly.
11. Operations Runbook
| Task | How |
|---|---|
| Health check | GET /health (router os/routers/health.py). Wire it to your load balancer. |
| Inspect a stuck run | GET /sessions/{id}/runs/{run_id}; cancel with POST /agents/{id}/runs/{run_id}/cancel. |
| Resume an interrupted run | POST /.../runs/{run_id}/continue or .../resume (used for human-in-the-loop and approvals). |
| Resolve a pending approval | GET /approvals, then POST /approvals/{id}/resolve. |
| Recompute metrics | POST /metrics/refresh. |
| Manage knowledge content | POST /knowledge/content, GET /knowledge/content/{id}/status, GET /knowledge/search. |
| Rename/clean sessions | POST /sessions/{id}/rename, DELETE /sessions/{id}. |
| Audit user memories | GET /memories, DELETE /memories/{id}, GET /user_memory_stats. |
11.1 Backups
Your db is the platform's state. Back it up on your normal cadence; a restore brings back every session, memory, trace, and saved component. Knowledge embeddings live in the vector DB — back that up too, or be prepared to re-ingest source documents.
11.2 Scaling guidance
- Throughput scales with replicas (stateless compute).
- Latency is dominated by the model provider; use
fallback_modelsto ride out provider slowdowns. - Context cost grows with history — cap
num_history_runs, enablecompress_tool_results=True, and use session summaries for long sessions to avoidModelProviderError: maximum context lengthfailures. - Run hooks in the background (
run_hooks_in_background=True) so guardrails/eval hooks don't block responses.
12. Internals & Module Reference
For engineers extending or debugging Agno. The codebase is large (~7.7M chars across libs/agno); the table below is the navigational map for the highest-traffic modules.
| Module | What lives there |
|---|---|
agno/agent/_run.py |
The core run loop — context assembly, model invocation, the tool-call cycle, retries, streaming. Start here for run behavior. |
agno/agent/_messages.py |
System/user message construction, knowledge retrieval injection, history assembly. |
agno/agent/_tools.py |
Tool resolution (Python fns, toolkits, MCP, callable factories), tool-choice handling. |
agno/agent/_session.py / _storage.py |
Session load/save, to_dict/from_dict, save/load of versioned components. |
agno/agent/_managers.py |
User-memory and cultural-knowledge management. |
agno/models/base.py |
The Model ABC; the provider-agnostic chat + tool-call protocol; JSON-serialization, error classification (ModelProviderError). |
agno/models/utils.py |
Model-string parsing ("provider:model_id"), provider resolution. |
agno/tools/toolkit.py |
Toolkit base + function registration. |
agno/tools/decorator.py |
The @tool decorator. |
agno/os/app.py |
AgentOS: router mounting, middleware, lifespan, serve. |
agno/os/routers/* |
One router package per resource (agents, teams, workflows, sessions, memory, knowledge, metrics, traces, schedules, approvals, components, evals, registry). |
agno/os/middleware/ |
JWT middleware, request context. |
agno/os/auth.py / scopes.py |
Token extraction + RBAC scope parsing/enforcement. |
agno/workflow/* |
Step graph primitives and the executor. |
agno/knowledge/ |
Readers, chunking strategies, embedders, rerankers, the Knowledge facade. |
agno/db/base.py |
BaseDb/AsyncBaseDb ABCs, ComponentType/SessionType enums. |
agno/registry/registry.py |
Component registry (reconstruct agents/teams from stored definitions). |
12.1 The Model interface (extending providers)
A provider adapter subclasses Model (agno/models/base.py) and implements the request/response/stream methods plus tool-call parsing. Provider classes live under agno/models/<provider>/ and are re-exported from that package's __init__.py (e.g. OpenAIChat, Claude, Gemini, Groq, MistralChat, AwsBedrock, AzureOpenAI). Error handling is centralized: providers raise ModelProviderError, which the run loop classifies as retryable (server errors, context-length) or fatal (invalid API key) to drive retries and fallbacks.
12.2 Component versioning & the registry
Agents, teams, and workflows can be persisted and versioned: agent.save(db=..., stage="published", label=...) writes a definition; Agent.load(id, db=...) reconstructs it. The Registry resolves nested references (a team's members, a workflow's steps) during load. This is what powers the /components and /registry endpoints and the "edit in the UI, reload without redeploy" workflow.
13. Code Quality & Conventions
- Typed throughout.
py.typedis shipped; mypy runs withpydantic.mypyplugin,check_untyped_defs,no_implicit_optional. Hundreds of third-party libs are listed under[[tool.mypy.overrides]]withignore_missing_importsbecause they are optional extras. - Ruff for linting/formatting, line length 120, target py39.
F401(unused import) is ignored in__init__.pyfiles because those re-export the public API. - Facade pattern. Large classes (
Agent,Team) are dataclasses whose methods delegate to private_*modules, keeping the public file readable while isolating heavy logic. Sync and async paths are maintained in parallel (x/ax). - Optional-by-default dependencies. Anything beyond the slim core is gated behind an import guard that raises a
pip install-instructionalImportError. This is a deliberate UX choice — keep it when adding integrations. - Backward compatibility. Deprecated constructor params are kept and mapped to their replacements with a
log_warning(e.g.enable_user_memories→update_memory_on_run,search_session_history→search_past_sessions). Honor this pattern when renaming.
14. Testing Strategy
Tests live under libs/agno/tests/ split into unit/, integration/, and system/. The agno[dev] and agno[tests] extras install the toolchain (pytest, pytest-asyncio, pytest-cov, pytest-mock, mypy, ruff, plus provider SDKs for model tests).
tests/unit/models/includes retry/error-classification suites that assert howModelProviderErrors (context-length, server errors, invalid key) drive retry vs. fail decisions — read these to understand resilience behavior.asyncio_mode = "auto"means async tests need no explicit marker.- Integration tests hit real provider/DB backends and are gated by the
integration-testsextra and credentials; run unit tests in CI by default.
cd libs/agno
pip install -e ".[dev]"
pytest tests/unit -q
15. Known Issues, Risks & Improvements
Derived from the community issue tracker and source structure:
| Area | Observation | Mitigation / Suggestion |
|---|---|---|
| Multi-turn reliability | A regression was reported where an agent failed multi-turn conversations on a specific version (GH #8258). | Pin a current version; verify db + add_history_to_context are set; add a smoke test for multi-turn. |
| Team coordination | Teams reported early termination / incomplete execution / first-chunk timeouts (GH #5326). | Raise max_iterations, give members clear roles, run long member tasks as background jobs; add per-member timeouts. |
| AG-UI integration | Event-ordering and response-divergence bugs against AG-UI (GH #5466, #5368). | Validate event sequencing when building custom AG-UI frontends; keep ag-ui-protocol current. |
| Vector DB params | Backend-specific param name mismatch reported for Milvus (drop_ratio_search vs drop_ratio_build, GH #5171). |
Validate vector-DB-specific search params against that backend's docs; don't assume cross-backend parity. |
| Supply chain | litellm/mistralai extras disabled due to PyPI incidents. |
Treat optional extras as part of your security review; pin and verify. |
| In-process scheduler | No external broker; multiple replicas all schedule. | Designate a single scheduler owner or coordinate via the DB for HA. |
| Surface size | The Agent/Team constructors expose 100+ params each. |
High flexibility, real onboarding cost — lean on cookbook/ recipes and start from a minimal agent, adding flags as needed. |
16. Quick Reference
Minimal production AgentOS
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.postgres import PostgresDb
from agno.os import AgentOS
db = PostgresDb(db_url="postgresql+psycopg://ai:ai@db:5432/agno")
assistant = Agent(name="Assistant", model=OpenAIChat(id="gpt-4o"), db=db)
agent_os = AgentOS(
agents=[assistant],
db=db,
authorization=True, # JWT + RBAC
tracing=True, # OpenTelemetry
scheduler=True, # cron jobs
telemetry=False, # no usage reporting
)
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve("my_os:app", host="0.0.0.0", port=7777, workers=4)
Production checklist
- [ ] Pin Agno and install only needed extras (
agno[os,postgres,pgvector,openai]==2.6.12). - [ ] Point
db(and vector DB) at managed, backed-up instances. - [ ]
authorization=TruewithJWT_VERIFICATION_KEY/JWT_JWKS_FILE, or a strongos_security_key. - [ ]
docs_enabled=False; lock downcors_allowed_origins. - [ ] Provider keys via secret manager;
AGNO_TELEMETRY=false. - [ ]
tracing=Truewired to your OTel collector;/healthwired to the load balancer. - [ ]
auto_provision_dbs=Falseafter first deploy; run migrations explicitly. - [ ] Single scheduler owner (or DB coordination) if
scheduler=Trueacross replicas. - [ ] Cap history (
num_history_runs) and enable summaries/compression for long sessions.
Key environment variables
| Variable | Purpose |
|---|---|
AGENT_OS_HOST / AGENT_OS_PORT |
Bind address/port (override serve). |
JWT_VERIFICATION_KEY / JWT_JWKS_FILE |
JWT auth (symmetric / asymmetric). |
AGNO_TELEMETRY |
false to disable usage telemetry. |
AGNO_API_RUNTIME |
stg for the staging control-plane link. |
<PROVIDER>_API_KEY |
Model provider credentials. |
Endpoint families
/agents · /teams · /workflows · /sessions · /memories · /knowledge · /metrics · /traces · /schedules · /approvals · /components · /eval-runs · /registry · /health — each with the run sub-resources (/runs, /runs/{id}, .../cancel, .../continue, .../resume) where applicable.