# AgentOS Authentication Source: https://docs.agno.com/agent-os/api/authentication Learn how to authenticate with AgentOS AgentOS supports bearer-token authentication to secure your API endpoints and protect your agentic systems from unauthorized access. ## Authentication Methods When a Security Key is configured, all API routes require an `Authorization: Bearer ` header for access. Without a key configured, authentication is disabled and all endpoints are publicly accessible. ### Using Bearer Token Authentication Include the authorization header in your API requests: ```bash theme={null} curl --location 'http://localhost:7777/agents/my-agent/runs' \ --header 'Authorization: Bearer your-secret-key' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'message=Your query here' ``` ### Configuration Set your security key when initializing AgentOS or through the configuration file. See the [AgentOS Security](/agent-os/security) guide for detailed setup instructions. ## Developer Resources * See [AgentOS Security](/agent-os/security) for comprehensive security configuration # API Usage Source: https://docs.agno.com/agent-os/api/usage Running your Agent / Team / Workflow with the AgentOS API The AgentOS API provides endpoints: * **Run an Agent**: `POST /agents/{agent_id}/runs` (See the [API reference](/reference-api/schema/agents/create-agent-run)) * **Run a Team**: `POST /teams/{team_id}/runs` (See the [API reference](/reference-api/schema/teams/create-team-run)) * **Run a Workflow**: `POST /workflows/{workflow_id}/runs` (See the [API reference](/reference-api/schema/workflows/execute-workflow)) These endpoints support form-based input. Below is an example of how to run an agent with the API: ```bash theme={null} curl --location 'http://localhost:7777/agents/agno-agent/runs' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'message=Tell me about Agno.' \ --data-urlencode 'stream=True' \ --data-urlencode 'user_id=john@example.com' \ --data-urlencode 'session_id=session_123' ``` ## Passing parameters to your Agent / Team / Workflow Agent, Team and Workflow `run()` and `arun()` endpoints support various runtime parameters. See the [Agent run schema](/reference/agents/agent#run), [Team run schema](/reference/teams/team#run), [Workflow run schema](/reference/workflows/workflow#run) for more details. It is a common pattern to want to pass `session_state`, `dependencies`, `metadata`, etc. to your Agent, Team or Workflow via the API. To pass these parameters via the AgentOS API, you can simply specify them as form-based parameters. Below is an example where `dependencies` are passed to the agent: ```python dependencies_to_agent.py theme={null} from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.os import AgentOS # Setup the database db = PostgresDb(id="basic-db", db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Setup basic agents, teams and workflows story_writer = Agent( id="story-writer-agent", name="Story Writer Agent", db=db, markdown=True, instructions="You are a story writer. You are asked to write a story about a robot. Always name the robot {robot_name}", ) # Setup our AgentOS app agent_os = AgentOS( description="Example AgentOS to show how to pass dependencies to an agent", agents=[story_writer], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="dependencies_to_agent:app", reload=True) ``` Then to test it, you can run the following command: ```bash theme={null} curl --location 'http://localhost:7777/agents/story-writer-agent/runs' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'message=Write me a 5 line story.' \ --data-urlencode 'dependencies={"robot_name": "Anna"}' ``` ## Cancelling a Run You can cancel a running agent, team or workflow by using the appropriate endpoint. For example, to cancel an agent run: ```bash theme={null} curl --location 'http://localhost:7777/agents/story-writer-agent/runs/123/cancel' ``` See the specific API references for more details: * [Cancel Agent Run API reference](/reference-api/schema/agents/cancel-agent-run) * [Cancel Team Run API reference](/reference-api/schema/teams/cancel-team-run) * [Cancel Workflow Run API reference](/reference-api/schema/workflows/cancel-workflow-run) ## Developer Resources * View [Complete API Reference](/reference-api/overview) for all endpoints * See [Authentication](/agent-os/api/authentication) for securing your API # AgentOS Configuration Source: https://docs.agno.com/agent-os/config Customize your AgentOS instance with custom configuration AgentOS configuration allows you to customize your instance for different environments and deployment scenarios. You can control which AI models are available globally and per-domain (for Evals), set custom display names for UI pages, define "quick prompts" for the chat interface, and configure per-database settings. This is particularly useful when managing multiple databases, deploying across different environments (development, staging, production), or building multi-tenant systems where each client needs distinct configurations. Configuring "Quick Prompts" can be particularly useful for improving the chat experience for users of your AgentOS. It changes the available options when your user creates a new session on the Chat Page. ## Setting your configuration You can provide your AgentOS configuration in two different ways: with a configuration YAML file, or using the `AgentOSConfig` class. See the full reference for the `AgentOSConfig` class [here](/reference/agent-os/configuration). ## Configuration YAML File 1. Create a YAML file with your configuration. For example: ```yaml theme={null} # Configure quick prompts for the Chat interface (per agent) chat: quick_prompts: marketing-agent: - "What can you do?" - "How is our latest post working?" - "Tell me about our active marketing campaigns" # Configure Memory page with custom display names memory: display_name: "User Memory Store" dbs: - db_id: db-0001 tables: ["custom_memory_table"] # Optional: specify custom table names domain_config: display_name: Main app user memories - db_id: db-0002 domain_config: display_name: Support flow user memories # Configure Knowledge page knowledge: display_name: "Knowledge Base" dbs: - db_id: db-0001 domain_config: display_name: Product documentation # Configure Session tracking session: display_name: "User Sessions" dbs: - db_id: db-0001 domain_config: display_name: Production sessions # Configure Evals page (supports both global and per-database available models) evals: display_name: "Evaluations" available_models: - "openai:gpt-4" - "anthropic:claude-sonnet-4" dbs: - db_id: db-0001 domain_config: display_name: Production evals available_models: - "openai:gpt-4o-mini" ``` 2. Pass the configuration to your AgentOS using the `config` parameter: ```python theme={null} from agno.os import AgentOS agent_os = AgentOS( name="My AgentOS", ..., config="path/to/configuration.yaml" ) ``` ## `AgentOSConfig` Class You can also provide your configuration using the `AgentOSConfig` class: ```python theme={null} from agno.os import AgentOS from agno.os.config import ( AgentOSConfig, ChatConfig, DatabaseConfig, EvalsConfig, EvalsDomainConfig, KnowledgeConfig, KnowledgeDomainConfig, MemoryConfig, MemoryDomainConfig, SessionConfig, SessionDomainConfig, ) agent_os = AgentOS( ..., config=AgentOSConfig( chat=ChatConfig( quick_prompts={ "marketing-agent": [ "What can you do?", "How is our latest post working?", "Tell me about our active marketing campaigns", ] } ), memory=MemoryConfig( display_name="User Memory Store", dbs=[ DatabaseConfig( db_id=marketing_db.id, domain_config=MemoryDomainConfig( display_name="Main app user memories", ), ), DatabaseConfig( db_id=support_db.id, domain_config=MemoryDomainConfig( display_name="Support flow user memories", ), ) ], ), ), ) ``` ## The /config endpoint The `/config` endpoint returns your complete AgentOS configuration as JSON. You could use this to inspect your AgentOS configuration that is served to the AgentOS Control Plane. The response includes: * **OS ID**: The ID of your AgentOS (automatically generated if not set) * **Description**: The description of your AgentOS * **Databases**: The list of IDs of the databases present in your AgentOS * **Agents**: The list of Agents available in your AgentOS * **Teams**: The list of Teams available in your AgentOS * **Workflows**: The list of Workflows available in your AgentOS * **Interfaces**: The list of Interfaces available in your AgentOS. E.g. WhatsApp, Slack, etc. * **Chat**: The configuration for the Chat page, which includes the list of quick prompts for each Agent, Team and Workflow in your AgentOS * **Session**: The configuration for the Session page of your AgentOS * **Metrics**: The configuration for the Metrics page of your AgentOS * **Memory**: The configuration for the Memory page of your AgentOS * **Knowledge**: The configuration for the Knowledge page of your AgentOS * **Evals**: The configuration for the Evals page of your AgentOS You will receive a JSON response with your configuration. Using the previous examples, you will receive: ```json theme={null} { "os_id": "0001", "name": "My AgentOS", "description": "Your AgentOS", "available_models": [ "openai:gpt-4", ], "databases": [ "db-0001", "db-0002" ], "agents": [], "chat": { "quick_prompts": { "marketing-agent": [ "What can you do?", "How is our latest post working?", "Tell me about our active marketing campaigns" ] } }, "memory": { "dbs": [ { "db_id": "db-0001", "domain_config": { "display_name": "Main app user memories" } }, { "db_id": "db-0002", "domain_config": { "display_name": "Support flow user memories" } } ] }, ... } ``` See the full schema for the `/config` endpoint [here](/reference-api/schema/core/get-os-configuration). # Connecting Your AgentOS Source: https://docs.agno.com/agent-os/connecting-your-os Step-by-step guide to connect your local AgentOS to the AgentOS Control Plane ## Overview Connecting your AgentOS is the critical first step to using the AgentOS Control Plane. This process establishes a connection between your running AgentOS instance and the Control Plane, allowing you to manage, monitor, and interact with your agents through the browser. **Prerequisites**: You need a running AgentOS instance before you can connect it to the Control Plane. If you haven't created one yet, check out our [Creating Your First OS](/agent-os/creating-your-first-os) guide. See the [AgentOS Control Plane](/agent-os/control-plane) documentation for more information about the Control Plane. ## Step-by-Step Connection Process ### 1. Access the Connection Dialog In the Agno platform: 1. Click on the team/organization dropdown in the top navigation bar 2. Click the **"+"** (plus) button next to "Add new OS" 3. The "Connect your AgentOS" dialog will open ### 2. Choose Your Environment Select **"Local"** for development or **"Live"** for production: * **Local**: Connects to an AgentOS running on your local machine * **Live**: Connects to a production AgentOS running on your infrastructure Live AgentOS connections require a PRO subscription. ### 3. Configure Connection Settings #### Endpoint URL * **Default Local**: `http://localhost:7777` * **Custom Local**: You can change the port if your AgentOS runs on a different port * **Live**: Enter your production HTTPS URL Make sure your AgentOS is actually running on the specified endpoint before attempting to connect. #### OS Name Give your AgentOS a descriptive name: * Use clear, descriptive names like "Development OS" or "Production Chat Bot" * This name will appear in your OS list and help you identify different instances #### Tags (Optional) Add tags to organize your AgentOS instances: * Examples: `development`, `production`, `chatbot`, `research` * Tags help filter and organize multiple OS instances * Click the **"+"** button to add multiple tags ### 4. Test and Connect 1. Click the **"CONNECT"** button 2. The platform will attempt to establish a connection to your AgentOS 3. If successful, you'll see your new OS in the organization dashboard ## Verifying Your Connection Once connected, you should see: 1. **OS Status**: "Running" indicator in the platform 2. **Available Features**: Chat, Knowledge, Memory, Sessions, etc. should be accessible 3. **Agent List**: Your configured agents should appear in the chat interface ## Securing Your Connection Protect your AgentOS APIs and Control Plane access with bearer-token authentication. Security keys provide essential protection for both development and production environments. **Key Features:** * Generate unique security keys per AgentOS instance * Rotate keys easily through the organization settings * Configure bearer-token authentication on your server For complete security setup instructions, including environment configuration and best practices, see the [Security Key](/agent-os/security) documentation. ## Managing Connected OS Instances ### Switching Between OS Instances 1. Use the dropdown in the top navigation bar 2. Select the OS instance you want to work with 3. All platform features will now connect to the selected OS ### Disconnecting an OS 1. Go to the organization settings 2. Find the OS in your list 3. Click the delete option Disconnecting an OS doesn't stop the AgentOS instance - it only removes it from the platform interface. ## Next Steps Once your AgentOS is successfully connected: Start having conversations with your connected agents Upload and organize your knowledge bases Track and analyze your agent interactions # Control Plane Source: https://docs.agno.com/agent-os/control-plane The main web interface for interacting with and managing your AgentOS instances The AgentOS Control Plane is your primary web interface for accessing and managing all AgentOS features. This intuitive dashboard serves as the central hub where you interact with your agents, manage knowledge bases, track sessions, monitor performance, and control user access. AgentOS Control Plane Dashboard ## OS Management Connect and inspect your OS runtimes from a single interface. Switch between local development and live production instances, monitor connection health, and configure endpoints for your different environments. ## User Management Manage your organization members and their access to AgentOS features. Configure your organization name, invite team members, and control permissions from a centralized interface. ### Inviting Members Add new team members to your organization by entering their email addresses. You can invite multiple users at once by separating emails with commas or pressing Enter/Tab between addresses. ### Member Roles Control what each member can access: * **Owner**: Full administrative access including billing and member management * **Member**: Access to AgentOS features and collaboration capabilities ## General Settings Configure your account preferences and organization settings. Access your profile information, manage billing and subscription details, and adjust organization-wide preferences from a centralized settings interface. ## Feature Access The control plane provides direct access to all main AgentOS capabilities through an intuitive interface: **Getting Started Tip**: The control plane is your gateway to all AgentOS features. Start by connecting your OS instance, then explore each feature section to familiarize yourself with the interface. Start conversations with your agents and access multi-agent interactions Upload and organize documents with search and browsing capabilities Browse stored memories and search through conversation history Track and analyze agent interactions and performance Test and evaluate agent performance with comprehensive metrics Monitor system performance and usage analytics ## Next Steps Ready to get started with the AgentOS control plane? Here's what you need to do: Set up a new AgentOS instance from scratch using our templates Learn how to connect your local development environment to the platform # Create Your First AgentOS Source: https://docs.agno.com/agent-os/creating-your-first-os Quick setup guide to get your first AgentOS instance running locally Get started with AgentOS by setting up a minimal local instance. This guide will have you running your first agent in minutes, with optional paths to add advanced features through our examples. AgentOS is a FastAPI app that you can run locally or in your cloud. If you want to build AgentOS using an existing FastAPI app, check out the [Custom FastAPI App](/agent-os/custom-fastapi/overview) guide. ## Prerequisites * Python 3.9+ * An LLM provider API key (e.g., `OPENAI_API_KEY`) ## Installation Create and activate a virtual environment: ```bash Mac theme={null} # Create virtual environment python -m venv venv # Activate virtual environment source venv/bin/activate ``` ```bash Windows theme={null} # Create virtual environment python -m venv venv # Activate virtual environment venv\Scripts\activate ``` Install dependencies: ```bash theme={null} pip install -U agno "fastapi[standard]" uvicorn openai ``` ## Minimal Setup Create `my_os.py`: ```python theme={null} from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS assistant = Agent( name="Assistant", model=OpenAIChat(id="gpt-5-mini"), instructions=["You are a helpful AI assistant."], markdown=True, ) agent_os = AgentOS( id="my-first-os", description="My first AgentOS", agents=[assistant], ) app = agent_os.get_app() if __name__ == "__main__": # Default port is 7777; change with port=... agent_os.serve(app="my_os:app", reload=True) ``` ## Running Your OS Start your AgentOS: ```bash theme={null} python my_os.py ``` Access your running instance: * **App Interface**: `http://localhost:7777` - Use this URL when connecting to the AgentOS control plane * **API Documentation**: `http://localhost:7777/docs` - Interactive API documentation and testing * **Configuration**: `http://localhost:7777/config` - View AgentOS configuration * **API Reference**: View the [AgentOS API documentation](/reference-api/overview) for programmatic access ## Connecting to the Control Plane With your AgentOS now running locally (`http://localhost:7777`), you can connect it to the AgentOS control plane for a enhanced management experience. The control plane provides a centralized interface to interact with your agents, manage knowledge bases, track sessions, and monitor performance. ## Next Steps Connect your running OS to the AgentOS control plane interface Explore comprehensive examples for advanced AgentOS configurations # Overriding Routes Source: https://docs.agno.com/agent-os/custom-fastapi/override-routes Learn how to override AgentOS routes with your own custom routes when conflicts occur When integrating your custom FastAPI application with AgentOS, route conflicts can occur if both your app and AgentOS define the same endpoint paths. For example, both might define a `/health` endpoint or a root `/` route. AgentOS provides the `on_route_conflict` parameter to control how these conflicts are resolved, allowing you to choose whether your custom routes or AgentOS routes take precedence. ## When to Use Override routes when you need: * **Custom health checks**: Replace AgentOS's `/health` endpoint with your own monitoring logic * **Branded landing pages**: Serve a custom homepage at `/` instead of the default AgentOS interface * **Custom authentication**: Implement your own auth endpoints that conflict with AgentOS defaults * **API versioning**: Control which version of an endpoint is exposed * **Custom error handlers**: Define specialized error handling for specific routes ## Configuration Options AgentOS provides two values for the `on_route_conflict` parameter for handling route conflicts: | Option | Custom Routes | AgentOS Routes | Warnings Logged | | ---------------------------- | ------------- | -------------------------- | --------------- | | `preserve_base_app` | ✓ Preserved | ✗ Skipped (conflicts only) | Yes | | `preserve_agentos` (default) | ✗ Overridden | ✓ Preserved | Yes | Non-conflicting routes from both your app and AgentOS are always included regardless of the mode. ## Example This example demonstrates using `on_route_conflict="preserve_base_app"` to preserve custom routes for the home page and health endpoint. ```python override_routes.py theme={null} from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.tools.duckduckgo import DuckDuckGoTools from fastapi import FastAPI # Set up the database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") web_research_agent = Agent( id="web-research-agent", name="Web Research Agent", model=Claude(id="claude-sonnet-4-0"), db=db, tools=[DuckDuckGoTools()], add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, ) # Create custom FastAPI app app: FastAPI = FastAPI( title="Custom FastAPI App", version="1.0.0", ) # Custom landing page (conflicts with AgentOS home route) @app.get("/") async def get_custom_home(): return { "message": "Custom FastAPI App", "note": "Using on_route_conflict=\"preserve_base_app\" to preserve custom routes", } # Custom health endpoint (conflicts with AgentOS health route) @app.get("/health") async def get_custom_health(): return {"status": "custom_ok", "note": "This is your custom health endpoint"} # Set up the AgentOS app by passing your FastAPI app # Use on_route_conflict="preserve_base_app" to preserve your custom routes over AgentOS routes agent_os = AgentOS( description="Example app with route replacement", agents=[web_research_agent], base_app=app, on_route_conflict="preserve_base_app", # Skip conflicting AgentOS routes, keep your custom routes ) app = agent_os.get_app() if __name__ == "__main__": """Run the AgentOS application. With on_route_conflict="preserve_base_app": - Your custom routes are preserved: http://localhost:7777/ and http://localhost:7777/health - AgentOS routes are available at other paths: http://localhost:7777/sessions, etc. - Conflicting AgentOS routes (GET / and GET /health) are skipped - API docs: http://localhost:7777/docs Try changing on_route_conflict to "preserve_agentos" to see AgentOS routes override your custom ones. """ agent_os.serve(app="override_routes:app", reload=True) ``` # Bring Your Own FastAPI App Source: https://docs.agno.com/agent-os/custom-fastapi/overview Learn how to use your own FastAPI app in your AgentOS AgentOS is built on FastAPI, which means you can easily integrate your existing FastAPI applications or add custom routes and routers to extend your agent's capabilities. ## Quick Start The simplest way to bring your own FastAPI app is to pass it to the AgentOS constructor: ```python theme={null} from fastapi import FastAPI from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS # Create your custom FastAPI app app = FastAPI(title="My Custom App") # Add your custom routes @app.get("/status") async def status_check(): return {"status": "healthy"} # Pass your app to AgentOS agent_os = AgentOS( agents=[Agent(id="basic-agent", model=OpenAIChat(id="gpt-5-mini"))], base_app=app # Your custom FastAPI app ) # Get the combined app with both AgentOS and your routes app = agent_os.get_app() ``` Your custom FastAPI app can have its own middleware and dependencies. If you have your own CORS middleware, it will be updated to include the AgentOS allowed origins, to make the AgentOS instance compatible with the Control Plane. Otherwise, the appropriate CORS middleware will be added to the app. ### Adding Middleware You can add any FastAPI middleware to your custom FastAPI app and it will be respected by AgentOS. Agno also provides some built-in middleware for common use cases, including authentication. See the [Middleware](/agent-os/middleware/overview) page for more details. ### Running with FastAPI CLI AgentOS applications are compatible with the [FastAPI CLI](https://fastapi.tiangolo.com/deployment/manually/) for development. First, install the FastAPI CLI: ```bash Install FastAPI CLI theme={null} pip install "fastapi[standard]" ``` Then run the app: ```bash Run with FastAPI CLI theme={null} fastapi run your_app.py ``` ```bash Run with auto-reload theme={null} fastapi run your_app.py --reload ``` ```bash Custom host and port theme={null} fastapi run your_app.py --host 0.0.0.0 --port 8000 ``` ### Running in Production For production deployments, you can use any ASGI server: ```bash Uvicorn theme={null} uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4 ``` ```bash Gunicorn with Uvicorn workers theme={null} gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 ``` ```bash FastAPI CLI (Production) theme={null} fastapi run main.py --host 0.0.0.0 --port 8000 ``` ## Adding Custom Routers For better organization, use FastAPI routers to group related endpoints: ```python custom_fastapi_app.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.tools.duckduckgo import DuckDuckGoTools from fastapi import FastAPI # Set up the database db = SqliteDb(db_file="tmp/agentos.db") # Set up the agent web_research_agent = Agent( name="Basic Agent", model=Claude(id="claude-sonnet-4-0"), db=db, tools=[DuckDuckGoTools()], add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, ) # Create custom FastAPI app app: FastAPI = FastAPI( title="Custom FastAPI App", version="1.0.0", ) # Add your own routes @app.post("/customers") async def get_customers(): return [ { "id": 1, "name": "John Doe", "email": "john.doe@example.com", }, { "id": 2, "name": "Jane Doe", "email": "jane.doe@example.com", }, ] # Set up the AgentOS app by passing your FastAPI app agent_os = AgentOS( description="Example app with custom routers", agents=[web_research_agent], base_app=app, ) # Alternatively, add all routes from AgentOS app to the current app # for route in agent_os.get_routes(): # app.router.routes.append(route) app = agent_os.get_app() if __name__ == "__main__": """Run the AgentOS application. You can see the docs at: http://localhost:7777/docs """ agent_os.serve(app="custom_fastapi_app:app", reload=True) ``` ## Middleware and Dependencies You can add middleware and dependencies to your custom FastAPI app: ```python theme={null} from fastapi import FastAPI, Depends, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.security import HTTPBearer app = FastAPI() # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["https://yourdomain.com"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Security dependency security = HTTPBearer() async def verify_token(token: str = Depends(security)): if token.credentials != "your-secret-token": raise HTTPException(status_code=401, detail="Invalid token") return token # Protected route @app.get("/protected", dependencies=[Depends(verify_token)]) async def protected_endpoint(): return {"message": "Access granted"} # Integrate with AgentOS agent_os = AgentOS( agents=[Agent(id="basic-agent", model=OpenAIChat(id="gpt-5-mini"))], base_app=app ) app = agent_os.get_app() ``` ## Access AgentOS Routes You can programmatically access and inspect the routes added by AgentOS: ```python theme={null} agent_os = AgentOS(agents=[agent]) app = agent_os.get_app() # Get all routes routes = agent_os.get_routes() for route in routes: print(f"Route: {route.path}") if hasattr(route, 'methods'): print(f"Methods: {route.methods}") ``` ## Developer Resources * [AgentOS Reference](/reference/agent-os/agent-os) * [Full Example](/agent-os/usage/custom-fastapi) * [FastAPI Documentation](https://fastapi.tiangolo.com/) # Chat Interface Source: https://docs.agno.com/agent-os/features/chat-interface Use AgentOS chat to talk to agents, collaborate with teams, and run workflows ## Overview The AgentOS chat is the home for day‑to‑day work with your AI system. From one screen you can: * Chat with individual agents * Collaborate with agent teams * Trigger and monitor workflows * Review sessions, knowledge, memory, and metrics It’s designed to feel familiar—type a message, attach files, and get live, streaming responses. Each agent, team, and workflow maintains its own context so you can switch between tasks without losing your place. ## Chat Interfaces ### Chat with an Agent * Select an agent from the right panel. * Ask a question like “What tools do you have access to?” * Agents keep their own history, tools, and instructions; switching agents won’t mix contexts. **Learn more about Agents**: Dive deeper into agent configuration, tools, memory, and advanced features in our [Agents Documentation](/basics/agents/overview). ### Work with a Team * Switch the top toggle to Teams and pick a team. * A team delegates tasks to its members and synthesizes their responses into a cohesive response. * Use the chat stream to watch how the team divides and solves the task. **Learn more about Teams**: Explore team modes, coordination strategies, and multi-agent collaboration in our [Teams Documentation](/basics/teams/overview). ### Run a Workflow * Switch to Workflows and choose one. * Provide the input (plain text or structured, depending on the workflow). * Watch execution live: steps stream as they start, produce output, and finish. **Learn more about Workflows**: Discover workflow types, advanced patterns, and automation strategies in our [Workflows Documentation](/basics/workflows/overview). ## Troubleshooting * The page loads but nothing responds: verify your AgentOS app is running. * Can’t see previous chats: you may be in a new session—open the Sessions panel and pick an older one. * File didn’t attach: try a common format (png, jpg, pdf, csv, docx, txt, mp3, mp4) and keep size reasonable. ## Related Examples Comprehensive demo with agents, knowledge, and evaluation system Advanced demo with knowledge, storage, and multiple agents Deploy agents to Slack channels Connect agents to WhatsApp messaging # Knowledge Management Source: https://docs.agno.com/agent-os/features/knowledge-management Upload, organize, and manage knowledge for your agents in AgentOS ## Overview Upload files, add web pages, or paste text to build a searchable knowledge base for your agents. AgentOS indexes content and shows processing status so you can track what’s ready to use. Prerequisites: Your AgentOS must be connected and active. If you see “Disconnected” or “Inactive,” review your{" "} connection settings. ## Accessing Knowledge * Open the `Knowledge` section in the sidebar. * If multiple knowledge databases are configured, select one from the database selector in the header. * Use the `Refresh` button to sync status and content. # Knowledge Management * **View Content**: Browse your Knowledge base contents * **Add Content**: Upload new documents, add URLs, or input text directly * **Edit Content**: Modify metadata on existing Knowledge entries * **Delete Content**: Remove outdated content ## What You Can Add * Files: `.pdf`, `.csv`, `.json`, `.txt`, `.doc`, `.docx` , `.md`, `.xlsx`, `.xls`, `.pptx`. * Web: Website URLs (pages) or direct file links * Text: Type or paste content directly Available processing options (Readers and Chunkers) are provided by your OS and may vary by file/URL type. ## Adding Content 1. Start an upload * Click `ADD NEW CONTENT`, then choose `FILE`, `WEB`, or `TEXT`. 2. FILE * Drag & drop or select files. You can also add a file URL. * Add details per item: Name, Description, Metadata, Reader, and optional Chunker. * Names must be unique across items. * Save to upload one or many at once. 3. WEB * Enter one or more URLs and add them to the list. * Add details per item as above (Name, Description, Metadata, Reader/Chunker). * Save to upload all listed URLs. 4. TEXT * Paste or type content. * Set Name, optional Description/Metadata, and Reader/Chunker. * Add Content to upload. ## Useful Links Learn how to add knowledge to agents and use RAG Understand knowledge sharing in team environments # Memories Source: https://docs.agno.com/agent-os/features/memories View and manage persistent memory storage for your agents in AgentOS ## Overview The Memories feature in AgentOS provides a centralized view of information that agents have learned and stored about you as a user. Memory gives agents the ability to recall information about you across conversations, enabling personalized and contextual interactions. * Memories are created and updated during an agent run * Each memory is tied to a specific user ID and contains learned information * Memories include content, topics, timestamps, and the input that generated them * Agents with memory enabled can learn about you and provide more relevant responses over time Prerequisites: Your AgentOS must be connected and active. If you see "Disconnected" or "Inactive," review your{" "} connection settings. ## Accessing Memories * Open the `Memory` section in the sidebar. * View all stored memories in a chronological table format. * Click the `Refresh` button to sync the latest memory updates. ## Memory Management The memory interface allows you to: 1. **Create memories** - Create memories your agents can reference during chat sessions 2. **View by topics** - See memories organized by thematic categories 3. **Edit memories** - Update or correct stored information as needed 4. **Delete memories** - Remove outdated or incorrect information 5. **Monitor memory creation** - See when and from what inputs memories were generated Memories are automatically generated from your conversations, but you can also manually create, edit, or remove them. ## Privacy and Control * All memories are tied to a specific user ID and stored in your AgentOS database * Memories are only accessible to agents within your connected OS instance * Memory data remains within your deployment and is never shared externally ## Useful Links Learn how memory works and how agents learn about users Understand data protection and privacy features # Session Tracking Source: https://docs.agno.com/agent-os/features/session-tracking Monitor, analyze, and manage agent sessions through the AgentOS interface ## Overview Sessions are durable conversation timelines that bind inputs, model outputs, tools, files, metrics, and summaries under a single `session_id`. AgentOS persists sessions for Agents, Teams, and Workflows so you can resume work, audit behavior, and analyze quality over time. * A session collects ordered runs (each run contains messages, tool calls, and metrics). * Summaries and metadata help you search, group, and reason about long histories. * Token usage can be monitored per session via the metrics tab. * Inspect details about the agent and models tied to each session. ## Accessing Sessions * Open the `Sessions` section in the sidebar. * If multiple session databases are configured, pick one from the database selector in the header. * Switch between `Agents` and `Teams` using the header tabs. * Click `Reload page` (Refresh) to sync the list and statuses. ## Troubleshooting * Sessions not loading: Ensure your OS is connected and active, select a session database, then click `Reload page`. * No sessions yet: Start a conversation to generate sessions. * Wrong list: Check the `Agents` vs `Teams` tab and sorting. * Configuration errors: If you see endpoint or database errors, verify your OS endpoint and database settings. ## Useful Links Learn about sessions and multi-turn conversations Understand chat history and multi-turn conversations # A2A Source: https://docs.agno.com/agent-os/interfaces/a2a/introduction Expose Agno agents via the A2A protocol v2.1.2 Google's [Agent-to-Agent Protocol (A2A)](https://a2a-protocol.org/latest/topics/what-is-a2a/) provides a standard way for agents to communicate with each other. Agno integrates with A2A, enabling Agno agents and teams to be exposed in an A2A-compatible format. The `A2A` interface works with the [AgentOS](/agent-os/introduction) runtime to provide this functionality. ## Setup Set `a2a_interface=True` when creating an `AgentOS` instance: ```python a2a_agentos.py theme={null} from agno.agent import Agent from agno.os import AgentOS from agno.os.interfaces.a2a import A2A agent = Agent(name="My Agno Agent") agent_os = AgentOS( agents=[agent], a2a_interface=True, ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="a2a:app", reload=True) ``` By default, all agents, teams, and workflows in the AgentOS are exposed via A2A. Specific agents, teams, and workflows can be exposed by initializing the interface explicitly: ```python a2a-interface-initialization.py theme={null} from agno.agent import Agent from agno.os import AgentOS from agno.os.interfaces.a2a import A2A agent = Agent(name="My Agno Agent") # Initialize the A2A interface specifying the agents to expose a2a = A2A(agents=[agent]) agent_os = AgentOS( agents=[agent], interfaces=[a2a], # Pass the A2A interface to the AgentOS using the `interfaces` parameter ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="a2a-interface-initialization:app", reload=True) ``` ## A2A API The A2A interface accepts A2A-compatible requests to run agents, teams, and workflows. Responses are returned in A2A-compatible format. See the [A2A API reference](/reference-api/schema/a2a/stream-message) for more details. ## Developer Resources * View [AgentOS Reference](/reference/agent-os/agent-os) * View [A2A Documentation](https://a2a-protocol.org/latest/) * View [Examples](/agent-os/usage/interfaces/a2a/basic) * View [Cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/agent_os/interfaces/a2a) # AG-UI Source: https://docs.agno.com/agent-os/interfaces/ag-ui/introduction Expose Agno agents via the AG-UI protocol AG-UI, the [Agent-User Interaction Protocol](https://github.com/ag-ui-protocol/ag-ui), standardizes how AI agents connect to frontend applications. **Migration from Apps**: For migration from `AGUIApp`, see the [v2 migration guide](/how-to/v2-migration#7-apps-interfaces) for complete steps. ## Example usage ```bash theme={null} pip install ag-ui-protocol ``` Expose an Agno agent through the AG-UI interface using `AgentOS` and `AGUI`. ```python basic.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.agui import AGUI chat_agent = Agent(model=OpenAIChat(id="gpt-4o")) agent_os = AgentOS(agents=[chat_agent], interfaces=[AGUI(agent=chat_agent)]) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", reload=True) ``` Use Dojo (`ag-ui`'s frontend) as an advanced, customizable interface for AG-UI agents. 1. Clone: `git clone https://github.com/ag-ui-protocol/ag-ui.git` 2. Install dependencies in `/ag-ui/typescript-sdk`: `pnpm install` 3. Build the Agno package in `/ag-ui/integrations/agno`: `pnpm run build` 4. Start Dojo following the instructions in the repository. With Dojo running, open `http://localhost:3000` and select the Agno agent. Additional examples are available in the [cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/agent_os/interfaces/agui/). ## Custom Events Custom events created in tools are automatically delivered to AG-UI in the AG-UI custom event format. **Creating custom events:** ```python theme={null} from dataclasses import dataclass from agno.run.agent import CustomEvent @dataclass class CustomerProfileEvent(CustomEvent): customer_name: str customer_email: str ``` **Yielding from tools:** ```python theme={null} from agno.tools import tool @tool() async def get_customer_profile(customer_id: str): customer = fetch_customer(customer_id) yield CustomerProfileEvent( customer_name=customer["name"], customer_email=customer["email"], ) return f"Profile retrieved for {customer['name']}" ``` Custom events are streamed in real-time to the AG-UI frontend. See [Custom Events documentation](/basics/agents/running-agents#custom-events) for more details. ## Core Components * `AGUI` (interface): Wraps an Agno `Agent` or `Team` into an AG-UI compatible FastAPI router. * `AgentOS.serve`: Serves the FastAPI app (including the AGUI router) with Uvicorn. `AGUI` mounts protocol-compliant routes on the app. ## `AGUI` interface Main entry point for AG-UI exposure. ### Initialization Parameters | Parameter | Type | Default | Description | | --------- | ----------------- | ------- | ---------------------- | | `agent` | `Optional[Agent]` | `None` | Agno `Agent` instance. | | `team` | `Optional[Team]` | `None` | Agno `Team` instance. | Provide `agent` or `team`. ### Key Method | Method | Parameters | Return Type | Description | | ------------ | ------------------------ | ----------- | -------------------------------------------------------- | | `get_router` | `use_async: bool = True` | `APIRouter` | Returns the AG-UI FastAPI router and attaches endpoints. | ## Endpoints Mounted at the interface's route prefix (root by default): * `POST /agui`: Main entrypoint. Accepts `RunAgentInput` from `ag-ui-protocol`. Streams AG-UI events. * `GET /status`: Health/status endpoint for the interface. Refer to `ag-ui-protocol` docs for payload details. ## Serving AgentOS Use `AgentOS.serve` to run the app with Uvicorn. ### Parameters | Parameter | Type | Default | Description | | --------- | --------------------- | ------------- | -------------------------------------- | | `app` | `Union[str, FastAPI]` | required | FastAPI app instance or import string. | | `host` | `str` | `"localhost"` | Host to bind. | | `port` | `int` | `7777` | Port to bind. | | `reload` | `bool` | `False` | Enable auto-reload for development. | See [cookbook examples](https://github.com/agno-agi/agno/tree/main/cookbook/agent_os/interfaces/agui/) for updated interface patterns. # Interfaces Source: https://docs.agno.com/agent-os/interfaces/overview Expose Agno agents through various communication protocols and platforms Interfaces enable exposing Agno agents, teams, and workflows through various communication protocols and platforms. Each interface provides a standardized way to connect Agno agents to external systems, messaging platforms, and frontend applications. ## Available Interfaces Connect agents to frontend applications using the Agent-User Interaction Protocol Deploy agents as Slack applications for team collaboration Serve agents via WhatsApp for direct messaging interactions Expose agents via the Agent-to-Agent Protocol for inter-agent communication ## How Interfaces Work Interfaces are FastAPI routers that mount protocol-specific endpoints on an AgentOS instance. Each interface: * Wraps Agno agents, teams, or workflows into protocol-compatible endpoints * Handles authentication and request validation for the target platform * Manages session tracking and context preservation * Streams responses back to clients in the appropriate format ## Using Interfaces Interfaces are added to an AgentOS instance through the `interfaces` parameter: ```python theme={null} from agno.os import AgentOS from agno.os.interfaces.slack import Slack agent_os = AgentOS( agents=[my_agent], interfaces=[Slack(agent=my_agent)], ) app = agent_os.get_app() ``` Multiple interfaces can be added to a single AgentOS instance, allowing the same agents to be exposed through different protocols simultaneously. # Slack Source: https://docs.agno.com/agent-os/interfaces/slack/introduction Host agents as Slack Applications. Use the Slack interface to serve Agents, Teams, or Workflows on Slack. It mounts Slack event routes on a FastAPI app and sends responses back to Slack threads. ## Setup Steps Follow the Slack setup guide in the [cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/agent_os/interfaces/slack/README.md). Required configuration: * `SLACK_TOKEN` (Bot User OAuth Token) * `SLACK_SIGNING_SECRET` (App Signing Secret) * An ngrok tunnel (for local development) and event subscriptions pointing to `/slack/events` ## Example Usage Create an agent, expose it with the `Slack` interface, and serve via `AgentOS`: ```python basic.py theme={null} from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.slack import Slack basic_agent = Agent( name="Basic Agent", model=OpenAIChat(id="gpt-5-mini"), # Ensure OPENAI_API_KEY is set add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, ) agent_os = AgentOS( agents=[basic_agent], interfaces=[Slack(agent=basic_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", port=8000, reload=True) ``` A complete example is available at `cookbook/agent_os/interfaces/slack/basic.py`. ## Core Components * `Slack` (interface): Wraps an Agno `Agent`, `Team`, or `Workflow` for Slack integration via FastAPI. * `AgentOS.serve`: Serves the FastAPI app using Uvicorn. ## `Slack` Interface Main entry point for Agno Slack applications. ### Initialization Parameters | Parameter | Type | Default | Description | | ------------------------ | --------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | `agent` | `Optional[Agent]` | `None` | Agno `Agent` instance. | | `team` | `Optional[Team]` | `None` | Agno `Team` instance. | | `workflow` | `Optional[Workflow]` | `None` | Agno `Workflow` instance. | | `prefix` | `str` | `"/slack"` | Custom FastAPI route prefix for the Slack interface. | | `tags` | `Optional[List[str]]` | `None` | FastAPI route tags for API documentation. Defaults to `["Slack"]` if not provided. | | `reply_to_mentions_only` | `bool` | `True` | When `True` (default), bot responds to @mentions in channels and all direct messages. When `False`, responds to all messages in channels. | Provide `agent`, `team`, or `workflow`. ### Key Method | Method | Parameters | Return Type | Description | | ------------ | ---------- | ----------- | -------------------------------------------------- | | `get_router` | None | `APIRouter` | Returns the FastAPI router and attaches endpoints. | ## Endpoints Mounted under the `/slack` prefix: ### `POST /slack/events` * Handles all Slack events (URL verification, messages, app mentions) * Verifies Slack signature on each request * Uses thread timestamps as session IDs for per-thread context * Streams responses back into the originating thread (splits long messages) ## Testing the Integration 1. Run the app locally: `python .py` (ensure ngrok is running) 2. Invite the bot to a channel: `/invite @YourAppName` 3. Mention the bot in a channel: `@YourAppName hello` 4. Open a DM with the bot and send a message ## Troubleshooting * Verify `SLACK_TOKEN` and `SLACK_SIGNING_SECRET` are set * Confirm the bot is installed and invited to the channel * Check ngrok URL and event subscription path (`/slack/events`) * Review application logs for signature failures or permission errors # WhatsApp Source: https://docs.agno.com/agent-os/interfaces/whatsapp/introduction Host agents as WhatsApp applications Use the WhatsApp interface to serve Agents or Teams via WhatsApp. It mounts webhook routes on a FastAPI app and sends responses back to WhatsApp users and threads. ## Setup Follow the WhatsApp setup guide in the [Whatsapp Cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/agent_os/interfaces/whatsapp/readme.md). Required environment variables: * `WHATSAPP_ACCESS_TOKEN` * `WHATSAPP_PHONE_NUMBER_ID` * `WHATSAPP_VERIFY_TOKEN` * Optional (production): `WHATSAPP_APP_SECRET` and `APP_ENV=production` The user's phone number is automatically used as the `user_id` for runs. This ensures that sessions and memory are appropriately scoped to the user. The phone number is also used for the `session_id`, so a single WhatsApp conversation corresponds to a single session. This should be considered when managing session history. ## Example Usage Create an agent, expose it with the `Whatsapp` interface, and serve via `AgentOS`: ```python theme={null} from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.whatsapp import Whatsapp image_agent = Agent( model=OpenAIChat(id="gpt-5-mini"), # Ensure OPENAI_API_KEY is set tools=[OpenAITools(image_model="gpt-image-1")], markdown=True, add_history_to_context=True, ) agent_os = AgentOS( agents=[image_agent], interfaces=[Whatsapp(agent=image_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", port=8000, reload=True) ``` Additional examples are available in the [cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/agent_os/interfaces/whatsapp/). ## Core Components * `Whatsapp` (interface): Wraps an Agno `Agent` or `Team` for WhatsApp via FastAPI. * `AgentOS.serve`: Serves the FastAPI app using Uvicorn. ## `Whatsapp` Interface Main entry point for Agno WhatsApp applications. ### Initialization Parameters | Parameter | Type | Default | Description | | --------- | ----------------- | ------- | ---------------------- | | `agent` | `Optional[Agent]` | `None` | Agno `Agent` instance. | | `team` | `Optional[Team]` | `None` | Agno `Team` instance. | Provide `agent` or `team`. ### Key Method | Method | Parameters | Return Type | Description | | ------------ | ------------------------ | ----------- | -------------------------------------------------- | | `get_router` | `use_async: bool = True` | `APIRouter` | Returns the FastAPI router and attaches endpoints. | ## Endpoints Mounted under the `/whatsapp` prefix: ### `GET /whatsapp/status` * Health/status of the interface. ### `GET /whatsapp/webhook` * Verifies WhatsApp webhook (`hub.challenge`). * Returns `hub.challenge` on success; `403` on token mismatch; `500` if `WHATSAPP_VERIFY_TOKEN` missing. ### `POST /whatsapp/webhook` * Receives WhatsApp messages and events. * Validates signature (`X-Hub-Signature-256`); bypassed in development mode. * Processes text, image, video, audio, and document messages via the agent/team. * Sends replies (splits long messages; uploads and sends generated images). * Responses: `200 {"status": "processing"}` or `{"status": "ignored"}`, `403` invalid signature, `500` errors. # What is AgentOS? Source: https://docs.agno.com/agent-os/introduction The production runtime and control plane for your agentic systems AgentOS is Agno's production-ready runtime that runs entirely within your own infrastructure, ensuring complete data privacy and control of your agentic system. Agno also provides a beautiful web interface for managing, monitoring, and interacting with your AgentOS, with no data ever being persisted outside of your environment. Behind the scenes, AgentOS is a FastAPI app that you can run locally or in your cloud. It is designed to be easy to deploy and scale. ## Getting Started Ready to get started with AgentOS? Here's what you need to do: Set up a new AgentOS instance from scratch using our templates Learn how to connect your local development environment to the platform ## Security & Privacy First AgentOS is designed with enterprise security and data privacy as foundational principles, not afterthoughts. AgentOS Security and Privacy Architecture ### Complete Data Ownership * **Your Infrastructure, Your Data**: AgentOS runs entirely within your cloud environment * **Zero Data Transmission**: No conversations, logs, or metrics are sent to external services * **Private by Default**: All processing, storage, and analytics happen locally To learn more about AgentOS Security, check out the [AgentOS Security](/agent-os/security) page. ## Learn more Learn how to use the AgentOS control plane to manage and monitor your OSs Get started by creating your first AgentOS instance # Filter Knowledge Source: https://docs.agno.com/agent-os/knowledge/filter-knowledge Learn how to use advanced filter expressions through the Agno API for precise knowledge base filtering. When using the AgentOS API, you can apply filters to precisely control which knowledge base documents your agents search, without changing your agent code. Filter expressions serialize to JSON and are automatically reconstructed server-side for powerful, programmatic filtering. ## Two Approaches to Filtering Agno supports two ways to filter knowledge through the API: * Use **dictionary filters** for simple "field = value" lookups * Use **filter expressions** when you need OR/NOT logic or ranges ### 1. Dictionary Filters (Simple) Best for straightforward equality matching. Send a JSON object with key-value pairs: ```json theme={null} {"docs": "agno", "status": "published"} ``` ### 2. Filter Expressions (Advanced) Best for complex filtering with full logical control. Send structured filter objects: ```json theme={null} {"op": "AND", "conditions": [ {"op": "EQ", "key": "docs", "value": "agno"}, {"op": "GT", "key": "version", "value": 2} ]} ``` **When to use which:** * Use **dict filters** for simple queries like filtering by category or status * Use **filter expressions** when you need OR logic, exclusions (NOT), or range queries (GT/LT) ## Filter Operators Filter expressions support a range of comparison and logical operators: ### Comparison Operators * **`EQ(key, value)`** - Equality: field equals value * **`GT(key, value)`** - Greater than: field > value * **`LT(key, value)`** - Less than: field \< value * **`IN(key, [values])`** - Inclusion: field in list of values ### Logical Operators * **`AND(*filters)`** - All conditions must be true * **`OR(*filters)`** - At least one condition must be true * **`NOT(filter)`** - Negate a condition ## Serialization Format Filter expression objects use a dictionary format with an `"op"` key that distinguishes them from regular dict filters: ```python theme={null} from agno.filters import EQ, GT, AND # Python filter expression filter_expr = AND(EQ("status", "published"), GT("views", 1000)) # Serialized to JSON { "op": "AND", "conditions": [ {"op": "EQ", "key": "status", "value": "published"}, {"op": "GT", "key": "views", "value": 1000} ] } ``` The presence of the `"op"` key tells the API to deserialize the filter as a filter expression. Regular dict filters (without `"op"`) continue to work for backward compatibility. ## Using Filters Through the API In all examples below, you pass the serialized JSON string via the `knowledge_filters` field when creating a run. ### Dictionary Filters (Simple Approach) For basic filtering, send a JSON object with key-value pairs. All conditions are combined with AND logic: ```python Python Client theme={null} import requests import json # Simple dict filter filter_dict = {"docs": "agno", "status": "published"} # Serialize to JSON filter_json = json.dumps(filter_dict) # Send request response = requests.post( "http://localhost:7777/agents/agno-knowledge-agent/runs", data={ "message": "What are agno's key features?", "stream": "false", "knowledge_filters": filter_json, } ) result = response.json() ``` ```bash cURL theme={null} curl -X 'POST' \ 'http://localhost:7777/agents/agno-knowledge-agent/runs' \ -H 'accept: application/json' \ -H 'Content-Type: multipart/form-data' \ -F 'message=What are agno'\''s key features?' \ -F 'stream=false' \ -F 'session_id=' \ -F 'user_id=' \ -F 'knowledge_filters={"docs": "agno"}' ``` **More Dict Filter Examples:** ```python theme={null} # Filter by single field {"category": "technology"} # Filter by multiple fields (AND logic) {"category": "technology", "status": "published", "year": 2024} # Filter with different data types {"active": True, "priority": 1, "department": "engineering"} ``` ### Filter Expressions (Advanced Approach) For complex filtering with logical operators and comparisons: ```python Python Client theme={null} import requests import json from agno.filters import EQ # Create filter expression filter_expr = EQ("category", "technology") # Serialize to JSON filter_json = json.dumps(filter_expr.to_dict()) # Send request response = requests.post( "http://localhost:7777/agents/my-agent/runs", data={ "message": "What are the latest tech articles?", "stream": "false", "knowledge_filters": filter_json, } ) result = response.json() ``` ```bash cURL theme={null} curl -X 'POST' \ 'http://localhost:7777/agents/my-agent/runs' \ -H 'Content-Type: multipart/form-data' \ -F 'message=What are the latest tech articles?' \ -F 'stream=false' \ -F 'knowledge_filters={"op": "EQ", "key": "category", "value": "technology"}' ``` ### Multiple Filter Expressions Send multiple filter expressions as a JSON array: ```python Python Client theme={null} from agno.filters import EQ, GT # Create multiple filters filters = [ EQ("status", "published"), GT("date", "2024-01-01") ] # Serialize list to JSON filters_json = json.dumps([f.to_dict() for f in filters]) response = requests.post( "http://localhost:7777/agents/my-agent/runs", data={ "message": "Show recent published articles", "stream": "false", "knowledge_filters": filters_json, } ) ``` ```bash cURL theme={null} curl -X 'POST' \ 'http://localhost:7777/agents/my-agent/runs' \ -H 'Content-Type: multipart/form-data' \ -F 'message=Show recent published articles' \ -F 'stream=false' \ -F 'knowledge_filters=[{"op": "EQ", "key": "status", "value": "published"}, {"op": "GT", "key": "date", "value": "2024-01-01"}]' ``` ## Error Handling ### Invalid Filter Structure When filters have errors, they're gracefully ignored with warnings: ```bash theme={null} # Missing required fields curl ... -F 'knowledge_filters={"op": "EQ", "key": "status"}' # Result: Filter ignored, warning logged # Unknown operator curl ... -F 'knowledge_filters={"op": "UNKNOWN", "key": "status", "value": "x"}' # Result: Filter ignored, warning logged # Invalid JSON curl ... -F 'knowledge_filters={invalid json}' # Result: Filter ignored, warning logged ``` When filters fail to parse, the search proceeds **without filters** rather than throwing an error. Always verify your filter JSON is valid and check server logs if results seem unfiltered. ### Client-Side Validation Add validation before sending requests: ```python theme={null} def validate_and_send_filter(filter_expr, message): """Validate filter before sending to API.""" try: # Test serialization filter_dict = filter_expr.to_dict() filter_json = json.dumps(filter_dict) # Verify it's valid JSON json.loads(filter_json) # Send request return send_filtered_agent_request(message, filter_expr) except (AttributeError, TypeError, json.JSONDecodeError) as e: print(f"Filter validation failed: {e}") return None ``` ## Next Steps Learn about filter expressions and metadata design in detail Explore the full Agent OS API reference Understand knowledge base architecture and setup Optimize your search strategies See working examples of filter expressions via API # Manage Knowledge Source: https://docs.agno.com/agent-os/knowledge/manage-knowledge Attach Knowledge to your AgentOS instance The AgentOS control plane provides a simple way to [manage](/agent-os/features/knowledge-management#adding-content) your Knowledge bases. You can add, edit, and delete content from your Knowledge bases directly through the control plane. You can specify multiple Knowledge bases and reuse the same Knowledge instance across different Agents or Teams as needed. ## Prerequisites Before setting up Knowledge management in AgentOS, ensure you have: * PostgreSQL database running and accessible - used for this example * Required dependencies installed: `pip install agno` * OpenAI API key configured (for embeddings) * Basic understanding of [Knowledge concepts](/basics/knowledge/getting-started) ## Example This example demonstrates how to attach multiple Knowledge bases to AgentOS and populate them with content from different sources. ```python agentos_knowledge.py theme={null} from textwrap import dedent from agno.db.postgres import PostgresDb from agno.knowledge.embedder.openai import OpenAIEmbedder from agno.knowledge.knowledge import Knowledge from agno.os import AgentOS from agno.vectordb.pgvector import PgVector, SearchType # ************* Setup Knowledge Databases ************* db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai" documents_db = PostgresDb( db_url, id="agno_knowledge_db", knowledge_table="agno_knowledge_contents", ) faq_db = PostgresDb( db_url, id="agno_faq_db", knowledge_table="agno_faq_contents", ) # ******************************* documents_knowledge = Knowledge( vector_db=PgVector( db_url=db_url, table_name="agno_knowledge_vectors", search_type=SearchType.hybrid, embedder=OpenAIEmbedder(id="text-embedding-3-small"), ), contents_db=documents_db, ) faq_knowledge = Knowledge( vector_db=PgVector( db_url=db_url, table_name="agno_faq_vectors", search_type=SearchType.hybrid, embedder=OpenAIEmbedder(id="text-embedding-3-small"), ), contents_db=faq_db, ) agent_os = AgentOS( description="Example app with AgentOS Knowledge", # Add the knowledge bases to AgentOS knowledge=[documents_knowledge, faq_knowledge], ) app = agent_os.get_app() if __name__ == "__main__": documents_knowledge.add_content( name="Agno Docs", url="https://docs.agno.com/llms-full.txt", skip_if_exists=True ) faq_knowledge.add_content( name="Agno FAQ", text_content=dedent(""" What is Agno? Agno is a framework for building agents. Use it to build multi-agent systems with memory, knowledge, human in the loop and MCP support. """), skip_if_exists=True, ) # Run your AgentOS # You can test your AgentOS at: http://localhost:7777/ agent_os.serve(app="agentos_knowledge:app") ``` ### Screenshots The screenshots below show how you can access and manage your different Knowledge bases through the AgentOS interface: llm-app-aidev-run llm-app-aidev-run ## Best Practices * **Separate Knowledge by Domain**: Create separate Knowledge bases for different topics (e.g., technical docs, FAQs, policies) * **Consistent Naming**: Use descriptive names for your Knowledge bases that reflect their content * **Regular Updates**: Keep your Knowledge bases current by regularly adding new content and removing outdated information * **Monitor Performance**: Use different table names for vector storage to avoid conflicts * **Content Organization**: Use the `name` parameter when adding content to make it easily identifiable * **Use metadata for filtering and searching**: Add metadata to your content to make it easier to find and filter ## Troubleshooting Ensure your knowledge base is properly added to the `knowledge` parameter when creating your AgentOS instance. Also make sure to attach a `contents_db` to your Knowledge instance. Verify your PostgreSQL connection string and ensure the database is running and accessible. Check that your content has been properly embedded by verifying entries in your vector database table. # Custom Lifespan Source: https://docs.agno.com/agent-os/lifespan Customize the lifespan of your AgentOS app to handle startup and shutdown logic. You will often want to run code before your AgentOS app starts or before it shuts down. This can be done by providing a custom **lifespan function** via the `lifespan` parameter. This is how a lifespan function looks like: ```python theme={null} @asynccontextmanager async def lifespan(app): # This will run before your app starts log_info("Starting My FastAPI App") yield # This will run before your app shuts down log_info("Stopping My FastAPI App") ``` ## FastAPI Lifespan The custom lifespan function you provide will be used as the **lifespan context manager** for the FastAPI app used by your AgentOS. Remember to decorate it with `@asynccontextmanager` as shown in the examples. See the [FastAPI documentation](https://fastapi.tiangolo.com/advanced/events/#lifespan-events) for more information about the lifespan context manager. If you are using a custom FastAPI app, you don't need to worry about overwriting its lifespan. The lifespan you provide will wrap the existing lifespan of the app, letting you combine all. ## Common Use Cases Lifespan control is useful to handle typical startup and shutdown tasks, such as: * **Resource Initialization**: databases, third party services, caches... or anything else needed by your app. * **Cleanup**: Close connections, store data or release resources before shut down. * **Health Checks**: Verify dependencies are available before serving requests * **Background Tasks**: Start/stop background processes ## Example ```python custom_lifespan.py theme={null} from contextlib import asynccontextmanager from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.utils.log import log_info # Setup the database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Setup basic agents, teams and workflows agno_support_agent = Agent( id="example-agent", name="Example Agent", model=Claude(id="claude-sonnet-4-0"), db=db, markdown=True, ) @asynccontextmanager async def lifespan(app): log_info("Starting My FastAPI App") yield log_info("Stopping My FastAPI App") agent_os = AgentOS( description="Example app with custom lifespan", agents=[agno_support_agent], lifespan=lifespan, ) app = agent_os.get_app() if __name__ == "__main__": """Run your AgentOS. You can see test your AgentOS at: http://localhost:7777/docs """ agent_os.serve(app="custom_lifespan:app") ``` ```bash theme={null} export ANTHROPIC_API_KEY=your_anthropic_api_key ``` ```bash theme={null} pip install -U agno anthropic "fastapi[standard]" uvicorn sqlalchemy ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash FastAPI CLI theme={null} fastapi run custom_lifespan.py ``` ```bash Mac theme={null} python custom_lifespan.py ``` ```bash Windows theme={null} python ovecustom_lifespanrride_routes.py ``` # AgentOS as MCP Server Source: https://docs.agno.com/agent-os/mcp/mcp Learn how and why to expose your AgentOS as an MCP server Your AgentOS will by default be exposed as an API. But you can also expose it as an **MCP server**. This is done by setting `enable_mcp_server=True` when creating your AgentOS instance: ```python theme={null} agent_os = AgentOS(enable_mcp_server=True) ``` ## Why use MCP? The [MCP protocol](https://modelcontextprotocol.io) has become the industry standard to handle connecting AI applications with external tools and data sources. By exposing your AgentOS as an MCP server, external clients that can handle MCP-compatible applications will be able to connect to your AgentOS and interact with it. ## Example ```python enable_mcp_example.py theme={null} from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.tools.duckduckgo import DuckDuckGoTools # Setup the database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Create your agents web_research_agent = Agent( name="Web Research Agent", model=Claude(id="claude-sonnet-4-0"), db=db, tools=[DuckDuckGoTools()], markdown=True, ) # Setup AgentOS with MCP enabled agent_os = AgentOS( description="Example app with MCP enabled", agents=[web_research_agent], enable_mcp_server=True, # This enables a LLM-friendly MCP server at /mcp ) app = agent_os.get_app() if __name__ == "__main__": # Your MCP server will be available at http://localhost:7777/mcp agent_os.serve(app="enable_mcp_example:app", reload=True) ``` Once enabled, your AgentOS will expose an MCP server via the `/mcp` endpoint. You can see a complete example [here](/agent-os/usage/mcp/enable-mcp-example). ## Available MCP Tools When you expose your AgentOS as an MCP server, the following MCP tools will be available: ### `get_agentos_config` Get the configuration of the AgentOS ### `run_agent` Run the desired Agent * `agent_id` (str): The ID of the agent to run * `message` (str): The message to send to the agent ### `run_team` Run the desired Team * `team_id` (str): The ID of the team to run * `message` (str): The message to send to the team ### `run_workflow` Run the desired Workflow * `workflow_id` (str): The ID of the workflow to run * `message` (str): The message to send to the workflow ### `get_sessions_for_agent` Get the list of sessions for the desired Agent * `agent_id` (str): The ID of the agent to get the sessions for * `db_id` (str): The ID of the database to use * `user_id` (Optional\[str]): The ID of the user to get the sessions for * `sort_by` (Optional\[str]): The field to sort the sessions by. Defaults to `created_at` * `sort_order` (Optional\[str]): The order to sort the sessions by. Defaults to `desc` ### `get_sessions_for_team` Get the list of sessions for the desired Team * `team_id` (str): The ID of the team to get the sessions for * `db_id` (str): The ID of the database to use * `user_id` (Optional\[str]): The ID of the user to get the sessions for * `sort_by` (Optional\[str]): The field to sort the sessions by. Defaults to `created_at` * `sort_order` (Optional\[str]): The order to sort the sessions by. Defaults to `desc` ### `get_sessions_for_workflow` Get the list of sessions for the desired Workflow * `workflow_id` (str): The ID of the workflow to get the sessions for * `db_id` (str): The ID of the database to use * `user_id` (Optional\[str]): The ID of the user to get the sessions for * `sort_by` (Optional\[str]): The field to sort the sessions by. Defaults to `created_at` * `sort_order` (Optional\[str]): The order to sort the sessions by. Defaults to `desc` ### `create_memory` Create a new user memory * `db_id` (str): The ID of the database to use * `memory` (str): The memory content to store * `user_id` (str): The user this memory is about * `topics` (Optional\[list\[str]]): The topics of the memory ### `get_memories_for_user` Get the list of memories for the given user * `user_id` (str): The ID of the user to get the memories for * `db_id` (Optional\[str]): The ID of the database to use * `sort_by` (Optional\[str]): The field to sort the memories by. Defaults to `created_at` * `sort_order` (Optional\[str]): The order to sort the memories by. Defaults to `desc` ### `update_memory` Update the desired memory * `db_id` (str): The ID of the database to use * `memory_id` (str): The ID of the memory to update * `memory` (str): The memory content to store * `user_id` (str): The ID of the user to update the memory for ### `delete_memory` Delete the desired memory * `db_id` (str): The ID of the database to use * `memory_id` (str): The ID of the memory to delete See a full example [here](/agent-os/usage/mcp/enable-mcp-example). # MCPTools within AgentOS Source: https://docs.agno.com/agent-os/mcp/tools Learn how to use MCPTools in the Agents, Teams and Workflows within your AgentOS The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) enables Agents to interact with external systems through a standardized interface. You can give your Agents access to MCP tools using the `MCPTools` class. Read more about using MCP tools [here](/basics/tools/mcp/overview). Your `MCPTools` will work normally within AgentOS. Their lifecycle is automatically handled, you don't need to handle their connection and disconnection. If you are using `MCPTools` within AgentOS, you should not use `reload=True` when serving your AgentOS. This can break the MCP connection during the FastAPI lifecycle. ## Example ```python mcp_tools_example.py theme={null} from agno.agent import Agent from agno.os import AgentOS from agno.tools.mcp import MCPTools # Create MCPTools instance mcp_tools = MCPTools( transport="streamable-http", url="https://docs.agno.com/mcp" ) # Create MCP-enabled agent agent = Agent( id="agno-agent", name="Agno Agent", tools=[mcp_tools], ) # AgentOS manages MCP lifespan agent_os = AgentOS( description="AgentOS with MCP Tools", agents=[agent], ) app = agent_os.get_app() if __name__ == "__main__": # Don't use reload=True with MCP tools to avoid lifespan issues agent_os.serve(app="mcp_tools_example:app") ``` Refreshing the connection to MCP servers is **not** automatically handled. You can use [`refresh_connection`](/basics/tools/mcp/overview#connection-refresh) to manually refresh a connection. See here for a [full example](/agent-os/usage/mcp/mcp-tools-example). # Custom Middleware Source: https://docs.agno.com/agent-os/middleware/custom Create custom middleware for rate limiting, logging, security, and monitoring in AgentOS v2.1.0 Each middleware wraps your application to intercept requests and responses, enabling you to implement cross-cutting concerns like authentication, logging, and rate limiting. AgentOS supports any [FastAPI/Starlette middleware](https://fastapi.tiangolo.com/tutorial/middleware/). You can create custom middleware for logging, rate limiting, monitoring, security, and more. ## Creating Custom Middleware Middleware in AgentOS follows the FastAPI/Starlette pattern using `BaseHTTPMiddleware`. See the following common middleware examples: ```python Rate Limiting theme={null} """ Rate limiting middleware that limits requests per IP address """ import time from collections import defaultdict, deque from fastapi import Request from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware class RateLimitMiddleware(BaseHTTPMiddleware): def __init__(self, app, requests_per_minute: int = 60): super().__init__(app) self.requests_per_minute = requests_per_minute self.request_history = defaultdict(lambda: deque()) async def dispatch(self, request: Request, call_next): client_ip = request.client.host if request.client else "unknown" current_time = time.time() # Clean old requests history = self.request_history[client_ip] while history and current_time - history[0] > 60: history.popleft() # Check rate limit if len(history) >= self.requests_per_minute: return JSONResponse( status_code=429, content={"detail": "Rate limit exceeded"} ) history.append(current_time) return await call_next(request) ``` ```python Request Logging theme={null} """ Log all requests with timing and metadata """ import logging import time from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware class LoggingMiddleware(BaseHTTPMiddleware): def __init__(self, app, log_body: bool = False): super().__init__(app) self.log_body = log_body self.logger = logging.getLogger("request_logger") async def dispatch(self, request: Request, call_next): start_time = time.time() client_ip = request.client.host if request.client else "unknown" # Log request self.logger.info(f"Request: {request.method} {request.url.path} from {client_ip}") # Optionally log body if self.log_body and request.method in ["POST", "PUT", "PATCH"]: body = await request.body() if body: self.logger.info(f"Body: {body.decode()}") response = await call_next(request) # Log response duration = (time.time() - start_time) * 1000 self.logger.info(f"Response: {response.status_code} in {duration:.1f}ms") return response ``` ```python Security Headers theme={null} """ Add security headers to all responses """ from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware class SecurityHeadersMiddleware(BaseHTTPMiddleware): def __init__(self, app): super().__init__(app) async def dispatch(self, request: Request, call_next): response = await call_next(request) # Add security headers response.headers["X-Content-Type-Options"] = "nosniff" response.headers["X-Frame-Options"] = "DENY" response.headers["X-XSS-Protection"] = "1; mode=block" response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains" response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" return response ``` ```python Request ID theme={null} """ Add unique request IDs for tracing """ import uuid from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware class RequestIDMiddleware(BaseHTTPMiddleware): def __init__(self, app): super().__init__(app) async def dispatch(self, request: Request, call_next): # Generate unique request ID request_id = str(uuid.uuid4()) # Store in request state request.state.request_id = request_id # Process request response = await call_next(request) # Add to response headers response.headers["X-Request-ID"] = request_id return response ``` ## Error Handling Handle exceptions in middleware: ```python theme={null} from fastapi import Request from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware import logging logger = logging.getLogger(__name__) class ErrorHandlingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): try: response = await call_next(request) return response except Exception as e: # Log the error logger.error(f"Request failed: {e}") # Return error response as JSONResponse return JSONResponse( status_code=500, content={"detail": "Internal server error"} ) ``` Error responses must be returned as `JSONResponse` objects to ensure proper serialization and HTTP status codes. ## Adding Middleware to AgentOS ```python custom_middleware.py theme={null} from agno.os import AgentOS from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") agent = Agent( name="Basic Agent", model=OpenAIChat(id="gpt-5-mini"), db=db, ) agent_os = AgentOS(agents=[agent]) app = agent_os.get_app() ``` ```python theme={null} # Add your custom middleware app.add_middleware( RateLimitMiddleware, requests_per_minute=100 ) app.add_middleware( LoggingMiddleware, log_body=False ) app.add_middleware(SecurityHeadersMiddleware) ``` ```python theme={null} if __name__ == "__main__": agent_os.serve(app="custom_middleware:app", reload=True) ``` ## Developer Resources Rate limiting and request logging middleware implementation. Custom FastAPI app with JWT middleware and AgentOS integration. Official FastAPI middleware documentation and examples. # JWT Middleware Source: https://docs.agno.com/agent-os/middleware/jwt Secure your AgentOS application with JWT token validation v2.1.0 Authenticate and authorize requests to your AgentOS application using JWT tokens. The middleware extracts tokens from Authorization headers or cookies, validates them, and automatically injects user\_id, session\_id, and custom claims into your endpoints. The JWT middleware provides two main features: 1. **Token Validation**: Validates JWT tokens and handles authentication 2. **Parameter Injection**: Automatically injects user\_id, session\_id, and custom claims into endpoint parameters ```python jwt_middleware_setup.py theme={null} from agno.os.middleware import JWTMiddleware from agno.os.middleware.jwt import TokenSource app.add_middleware( JWTMiddleware, secret_key="your-jwt-secret-key", # or use JWT_SECRET_KEY environment variable algorithm="HS256", user_id_claim="sub", # Extract user_id from 'sub' claim session_id_claim="session_id", # Extract session_id from claim dependencies_claims=["name", "email", "roles"], # Additional claims validate=True, # Enable token validation ) ``` ## Token Sources The middleware supports three token sources: Extract JWT from `Authorization: Bearer ` header. ```python theme={null} from agno.os.middleware.jwt import TokenSource app.add_middleware( JWTMiddleware, secret_key="your-secret", token_source=TokenSource.HEADER, # Default ) ``` Extract JWT from HTTP-only cookies for web applications. ```python theme={null} app.add_middleware( JWTMiddleware, secret_key="your-secret", token_source=TokenSource.COOKIE, cookie_name="access_token", # Default ) ``` Try both header and cookie (header takes precedence). ```python theme={null} app.add_middleware( JWTMiddleware, secret_key="your-secret", token_source=TokenSource.BOTH, cookie_name="access_token", # Default token_header_key="Authorization", # Default ) ``` ## Parameter Injection The middleware automatically injects JWT claims into AgentOS endpoints. The following parameters are extracted from tokens and injected into requests: * `user_id` - User identifier from token claims * `session_id` - Session identifier from token claims * `dependencies` - Custom claims for agent tools * `session_state` - Custom claims for session management For example, the `/agents/{agent_id}/runs` endpoint automatically uses `user_id`, `session_id`, `dependencies`, and `session_state` from the JWT token when available. This is useful for: * Automatically using the `user_id` and `session_id` from your JWT token when running an agent * Automatically filtering sessions retrieved from `/sessions` endpoints by `user_id` (where applicable) * Automatically injecting `dependencies` from claims in your JWT token into the agent run, which then is available on tools called by your agent View the [full example](/agent-os/usage/middleware/jwt-middleware) for more details. ## Security Features Use strong secret keys, store them securely (not in code), and enable validation in production. **Token Validation**: When `validate=True`, the middleware: * Verifies JWT signature using the secret key * Checks token expiration (`exp` claim) * Returns 401 errors for invalid/expired tokens **HTTP-Only Cookies**: When using cookies: * Set `httponly=True` to prevent JavaScript access (XSS protection) * Set `secure=True` for HTTPS-only transmission * Set `samesite="strict"` for CSRF protection ## Excluded Routes Skip middleware for specific routes: ```python jwt_excluded_routes.py theme={null} app.add_middleware( JWTMiddleware, secret_key="your-secret", excluded_route_paths=[ "/health", "/auth/login", "/auth/register", "/public/*", # Wildcards supported ] ) ``` ## Configuration Options | Parameter | Description | Default | | ---------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | | `secret_key` | Secret key for JWT verification | Optional, will use `JWT_SECRET_KEY` environment variable if not provided | | `algorithm` | JWT algorithm (HS256, RS256, etc.) | "HS256" | | `token_source` | Where to extract token from. `HEADER`, `COOKIE`, or `BOTH`. | `TokenSource.HEADER` | | `token_header_key` | Key to use for the Authorization header (only used when token\_source is `HEADER` or `BOTH`) | "Authorization" | | `cookie_name` | Cookie name when using cookies (only used when token\_source is `COOKIE` or `BOTH`) | "access\_token" | | `validate` | Enable token validation | `True` | | `excluded_route_paths` | Routes to skip middleware (useful for health checks, etc.) | `None` | | `scopes_claim` | JWT claim for scopes | `None` | | `user_id_claim` | JWT claim for user ID | "sub" | | `session_id_claim` | JWT claim for session ID | "session\_id" | | `dependencies_claims` | List of additional claims to extract for `dependencies` parameter | `[]` | | `session_state_claims` | List of additional claims to extract for `session_state` parameter | `[]` | ### Examples JWT authentication using Authorization headers for API clients. JWT authentication using HTTP-only cookies for web applications. Custom FastAPI app with JWT middleware and AgentOS integration. ### External Resources Official PyJWT library documentation for JWT encoding and decoding. # AgentOS Middleware Source: https://docs.agno.com/agent-os/middleware/overview Add authentication, logging, monitoring, and security features to your AgentOS application using middleware v2.1.0 AgentOS is built on FastAPI, allowing you to add any [FastAPI/Starlette compatible middleware](https://fastapi.tiangolo.com/tutorial/middleware/) for authentication, logging, monitoring, and security. Agno provides built-in JWT middleware for authentication, and you can create custom middleware for rate limiting, request logging, and security headers. Additionally, Agno provides some built-in middleware for common use cases, including authentication. See the following guides: Create your own middleware for logging, rate limiting, monitoring, and security. Built-in JWT authentication with automatic parameter injection and claims extraction. ## Quick Start Adding middleware to your AgentOS application is straightforward: ```python agent_os_with_jwt_middleware.py theme={null} from agno.os import AgentOS from agno.os.middleware import JWTMiddleware from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.agent import Agent db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") agent = Agent( name="Basic Agent", model=OpenAIChat(id="gpt-5-mini"), db=db, ) # Create your AgentOS app agent_os = AgentOS(agents=[agent]) app = agent_os.get_app() # Add middleware app.add_middleware( JWTMiddleware, secret_key="your-secret-key", validate=True ) if __name__ == "__main__": agent_os.serve(app="agent_os_with_jwt_middleware:app", reload=True) ``` Test middleware thoroughly in your own staging environment before production deployment. **Performance Impact:** Each middleware adds latency to requests ## Common Use Cases **Secure your AgentOS with JWT authentication:** * Extract tokens from headers or cookies * Automatic parameter injection (user\_id, session\_id) * Custom claims extraction for `dependencies` and `session_state` * Route exclusion for public endpoints [Learn more about JWT Middleware](/agent-os/middleware/jwt) **Prevent API abuse with rate limiting:** ```python theme={null} class RateLimitMiddleware(BaseHTTPMiddleware): def __init__(self, app, requests_per_minute: int = 60): super().__init__(app) self.requests_per_minute = requests_per_minute # ... implementation app.add_middleware(RateLimitMiddleware, requests_per_minute=100) ``` **Monitor requests and responses:** ```python theme={null} class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time # Log request details... return response ``` ## Middleware Execution Order Middleware is executed in reverse order of addition. The last middleware added runs first. ```python theme={null} app.add_middleware(MiddlewareA) # Runs third (closest to route) app.add_middleware(MiddlewareB) # Runs second app.add_middleware(MiddlewareC) # Runs first (outermost) # Request: C -> B -> A -> Your Route # Response: Your Route -> A -> B -> C ``` **Best Practice:** Add middleware in logical order: 1. **Security middleware first** (CORS, security headers) 2. **Authentication middleware** (JWT, session validation) 3. **Monitoring middleware** (logging, metrics) 4. **Business logic middleware** (rate limiting, custom logic) ## Developer Resources ### Examples JWT authentication using Authorization headers for API clients. JWT authentication using HTTP-only cookies for web applications. Rate limiting and request logging middleware implementation. Custom FastAPI app with JWT middleware and AgentOS integration. ### External Resources Official FastAPI middleware documentation and examples. Starlette middleware reference and implementation guides. # AgentOS Source: https://docs.agno.com/agent-os/overview Agno's production runtime and control plane for your agentic systems AgentOS is Agno's production runtime and control plane for deploying and managing your agentic systems at scale. Built on [FastAPI](https://fastapi.tiangolo.com/), it provides a robust, scalable infrastructure that you can run locally during development or deploy to your cloud environment for production workloads. AgentOS serves as the central hub for your AI agents, teams, and workflows, providing a unified API for execution, monitoring, and management. Whether you're running a single agent or orchestrating complex multi-agent systems, AgentOS gives you the tools to build production-ready agentic applications. With AgentOS, you can: * **Run Agents / Teams / Workflows**: Create new runs for your agents, teams and workflows, either with a new session or a existing one. * **Manage Sessions**: Retrieve, update and delete sessions. * **Manage Memories**: Retrieve, update and delete memories. * **Manage Knowledge**: Manage the content of your knowledge base. * **Manage Evals**: Retrieve, create, delete and update evals. This is the same API that powers the [AgentOS Control Plane](/agent-os/control-plane). However, you can also use these endpoints to power your own application! See the full [API reference](/reference-api/overview) for more details. ## Create your AgentOS Below is a basic example of how to create an AgentOS instance: ```python my_os.py theme={null} from agno.os import AgentOS agent_os = AgentOS( name="My AgentOS", description="My Multi-Agent Runtime", agents=[basic_agent], teams=[basic_team], workflows=[basic_workflow] ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="my_os:app", reload=True) ``` You can configure the behaviour of your AgentOS by passing the following parameters to the `AgentOS` class: * `agents`: List of agents to include in the AgentOS * `teams`: List of teams to include in the AgentOS * `workflows`: List of workflows to include in the AgentOS * `knowledge`: List of knowledge instances to include in the AgentOS * `interfaces`: List of interfaces to include in the AgentOS * See the [Interfaces](/agent-os/interfaces) section for more details. * `config`: Configuration file path or `AgentOSConfig` instance * See the [Configuration](/agent-os/config) page for more details. * `base_app`: Optional custom FastAPI app to use instead of creating a new one * See the [Custom FastAPI App](/agent-os/custom-fastapi/overview) page for more details. * `lifespan`: Optional lifespan context manager for the FastAPI app * See the [Lifespan](/agent-os/lifespan) page for more details. * `enable_mcp_server`: Turn your AgentOS into an MCP server * See the [MCP enabled AgentOS](/agent-os/mcp/mcp) page for more details. See the [AgentOS class reference](/reference/agent-os/agent-os) for more details. ## Learn more Learn how to authenticate with AgentOS Learn how to use the AgentOS API to run your Agent / Team / Workflow Learn how to configure your AgentOS to your needs # AgentOS Security Source: https://docs.agno.com/agent-os/security Learn how to secure your AgentOS instance with a security key ## Overview AgentOS supports bearer-token authentication to secure your instance. When a Security Key is configured, all API routes require an `Authorization: Bearer ` header for access. Without a key configured, authentication is disabled. You can generate a security key from the AgentOS Control Plane, which also enables secure communication between your AgentOS and the Control Plane. ## Generate a Security Key From the AgentOS control plane, generate a security key or set your own. You can also create your own security key and set it on the AgentOS UI. ## Security Key Authentication Set the `OS_SECURITY_KEY` environment variable where your AgentOS server runs. When present, the server automatically enforces bearer authentication on all API routes. ### macOS / Linux (bash or zsh) ```bash theme={null} export OS_SECURITY_KEY="OSK_...your_copied_key..." uvicorn app:app --host 0.0.0.0 --port 8000 ``` ### Docker Compose ```yaml theme={null} services: agentos: image: your-org/agentos:latest environment: - OS_SECURITY_KEY=${OS_SECURITY_KEY} ports: - "8000:8000" ``` **How it works**: AgentOS reads `OS_SECURITY_KEY` into the AgentOS router's internal authorization logic. If configured, requests without a valid `Authorization: Bearer` header return `401 Unauthorized`. ### Key Rotation 1. In the UI, click the **Generate** icon next to "Security Key" to generate a new value 2. Update the server's `OS_SECURITY_KEY` environment variable and reload/redeploy AgentOS 3. Update all clients, workers, and CI/CD systems that call the AgentOS API ### Security Best Practices * **Environment Isolation**: Use different keys per environment with least-privilege distribution * **Code Safety**: Never commit keys to version control or print them in logs ### Troubleshooting * **401 Unauthorized**: Verify the header format is exactly `Authorization: Bearer ` and that the server has `OS_SECURITY_KEY` configured * **Local vs Production**: Confirm your local shell exported `OS_SECURITY_KEY` before starting the application * **Post-Rotation Failures**: Ensure all clients received the new key. Restart CI/CD runners that may cache environment variables * **Connection Issues**: Check that your AgentOS instance is running and accessible at the configured endpoint ## JWT Authentication AgentOS provides a middleware solution for custom JWT authentication. Learn more about [JWT Middleware](/agent-os/middleware/jwt) Although the JWT Middleware is already powerful feature, Agno is working on further extending authentication capabilities and better role-based access control in AgentOS. # AgentOS Demo Source: https://docs.agno.com/agent-os/usage/demo AgentOS demo with agents and teams Here is a full example of an AgentOS with multiple agents and teams. It also shows how to instantiate agents with a database, knowledge base, and tools. ## Code ```python cookbook/agent_os/demo.py theme={null} """ AgentOS Demo Prerequisites: pip install -U fastapi uvicorn sqlalchemy pgvector psycopg openai ddgs mcp """ from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.knowledge.knowledge import Knowledge from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.team import Team from agno.tools.duckduckgo import DuckDuckGoTools from agno.tools.mcp import MCPTools from agno.vectordb.pgvector import PgVector # Database connection db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai" # Create Postgres-backed memory store db = PostgresDb(db_url=db_url) # Create Postgres-backed vector store vector_db = PgVector( db_url=db_url, table_name="agno_docs", ) knowledge = Knowledge( name="Agno Docs", contents_db=db, vector_db=vector_db, ) # Create your agents agno_agent = Agent( name="Agno Agent", model=OpenAIChat(id="gpt-4.1"), tools=[MCPTools(transport="streamable-http", url="https://docs.agno.com/mcp")], db=db, enable_user_memories=True, knowledge=knowledge, markdown=True, ) simple_agent = Agent( name="Simple Agent", role="Simple agent", id="simple_agent", model=OpenAIChat(id="gpt-5-mini"), instructions=["You are a simple agent"], db=db, enable_user_memories=True, ) research_agent = Agent( name="Research Agent", role="Research agent", id="research_agent", model=OpenAIChat(id="gpt-5-mini"), instructions=["You are a research agent"], tools=[DuckDuckGoTools()], db=db, enable_user_memories=True, ) # Create a team research_team = Team( name="Research Team", description="A team of agents that research the web", members=[research_agent, simple_agent], model=OpenAIChat(id="gpt-5-mini"), id="research_team", instructions=[ "You are the lead researcher of a research team! 🔍", ], db=db, enable_user_memories=True, add_datetime_to_context=True, markdown=True, ) # Create the AgentOS agent_os = AgentOS( id="agentos-demo", agents=[agno_agent], teams=[research_team], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="demo:app", port=7777) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key export OS_SECURITY_KEY=your_security_key # Optional for authentication ``` ```bash theme={null} pip install -U fastapi uvicorn sqlalchemy pgvector psycopg openai ddgs mcp agno ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash Mac theme={null} python cookbook/agent_os/demo.py ``` ```bash Windows theme={null} python cookbook/agent_os/demo.py ``` # AgentOS Configuration Source: https://docs.agno.com/agent-os/usage/extra-configuration Passing extra configuration to your AgentOS ## Configuration file We will first create a YAML file with the extra configuration we want to pass to our AgentOS: ```yaml configuration.yaml theme={null} chat: quick_prompts: marketing-agent: - "What can you do?" - "How is our latest post working?" - "Tell me about our active marketing campaigns" memory: dbs: - db_id: db-0001 domain_config: display_name: Main app user memories - db_id: db-0002 domain_config: display_name: Support flow user memories ``` ## Code ```python cookbook/agent_os/os_config/yaml_config.py theme={null} """Example showing how to pass extra configuration to your AgentOS.""" from pathlib import Path from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.knowledge.knowledge import Knowledge from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.team import Team from agno.vectordb.pgvector import PgVector from agno.workflow.step import Step from agno.workflow.workflow import Workflow # Get the path to our configuration file cwd = Path(__file__).parent config_file_path = str(cwd.joinpath("configuration.yaml")) # Setup the database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Setup basic agents, teams and workflows basic_agent = Agent( name="Basic Agent", db=db, enable_session_summaries=True, enable_user_memories=True, add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, ) basic_team = Team( id="basic-team", name="Basic Team", model=OpenAIChat(id="gpt-5-mini"), db=db, members=[basic_agent], enable_user_memories=True, ) basic_workflow = Workflow( id="basic-workflow", name="Basic Workflow", description="Just a simple workflow", db=db, steps=[ Step( name="step1", description="Just a simple step", agent=basic_agent, ) ], ) basic_knowledge = Knowledge( name="Basic Knowledge", description="A basic knowledge base", contents_db=db, vector_db=PgVector(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai", table_name="vectors"), ) # Setup our AgentOS app agent_os = AgentOS( description="Example AgentOS", agents=[basic_agent], teams=[basic_team], workflows=[basic_workflow], knowledge=[basic_knowledge], # We pass the configuration file to our AgentOS here config=config_file_path, ) app = agent_os.get_app() if __name__ == "__main__": """Run our AgentOS. You can see the configuration and available apps at: http://localhost:7777/config """ agent_os.serve(app="yaml_config:app", reload=True) ``` It's recommended to add `id` for better management and easier identification in the AgentOS interface. You can add it to your database configuration like this: ```python theme={null} from agno.db.postgres import PostgresDb db = PostgresDb( id="my_agent_db", db_url="postgresql+psycopg://ai:ai@localhost:5532/ai" ) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno fastapi uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash Mac theme={null} python cookbook/agent_os/os_config/yaml_config.py ``` ```bash Windows theme={null} python cookbook/agent_os/os_config/yaml_config.py ``` # Human-in-the-Loop Example Source: https://docs.agno.com/agent-os/usage/hitl AgentOS with tools requiring user confirmation This example shows how to implement Human-in-the-Loop in AgentOS. When an agent needs to execute a tool that requires confirmation, the run pauses and waits for user approval before proceeding. ## Prerequisites * Python 3.10 or higher * PostgreSQL with pgvector (setup instructions below) * OpenAI API key ## Code ```python hitl_confirmation.py theme={null} from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.tools import tool # Database connection db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai" db = PostgresDb(db_url=db_url) @tool(requires_confirmation=True) def delete_records(table_name: str, count: int) -> str: """Delete records from a database table. Args: table_name: Name of the table count: Number of records to delete Returns: str: Confirmation message """ return f"Deleted {count} records from {table_name}" @tool(requires_confirmation=True) def send_notification(recipient: str, message: str) -> str: """Send a notification to a user. Args: recipient: Email or username of the recipient message: Notification message Returns: str: Confirmation message """ return f"Sent notification to {recipient}: {message}" # Create agent with HITL tools agent = Agent( name="Data Manager", id="data_manager", model=OpenAIChat(id="gpt-4o-mini"), tools=[delete_records, send_notification], instructions=["You help users manage data operations"], db=db, markdown=True, ) # Create AgentOS agent_os = AgentOS( id="agentos-hitl", agents=[agent], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="hitl_confirmation:app", port=7777) ``` ## Testing the Example Once the server is running, test the HITL flow: ```bash theme={null} # 1. Send a request that requires confirmation curl -X POST http://localhost:7777/agents/data_manager/runs \ -F "message=Delete 50 old records from the users table" \ -F "user_id=test_user" \ -F "session_id=test_session" # The response will have status: "paused" with tools awaiting confirmation # 2. Continue with approval (use the run_id and tool_call_id from response) curl -X POST http://localhost:7777/agents/data_manager/runs/{run_id}/continue \ -F "tools=[{\"tool_call_id\": \"{tool_call_id}\", \"confirmed\": true}]" \ -F "session_id=test_session" \ -F "stream=false" ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno fastapi uvicorn sqlalchemy pgvector psycopg openai ``` ```bash theme={null} docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash theme={null} python hitl_confirmation.py ``` ## Learn More Learn HITL basics with a simple example Understand HITL patterns and best practices # Agent with Tools Source: https://docs.agno.com/agent-os/usage/interfaces/a2a/agent-with-tools Investment analyst agent with financial tools and web interface ## Code ```python a2a_agent_with_tools.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.a2a import A2A from agno.tools.yfinance import YFinanceTools agent = Agent( model=OpenAIChat(id="gpt-5-mini"), tools=[ DuckDuckGoTools(), ], description="You are an investment analyst that researches stock prices, analyst recommendations, and stock fundamentals.", instructions="Format your response using markdown and use tables to display data where possible.", ) agent_os = AgentOS( agents=[agent], a2a_interface=True, ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="a2a_agent_with_tools:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai ddgs a2a-protocol ``` ```bash Mac theme={null} python a2a_agent_with_tools.py ``` ```bash Windows theme={null} python a2a_agent_with_tools.py ``` ## Key Features * **Financial Data Tools**: Real-time stock prices, analyst recommendations, fundamentals via web searches * **Investment Analysis**: Comprehensive company analysis and recommendations * **Data Visualization**: Tables and formatted financial information * **Web Interface**: Professional browser-based interaction * **GPT-5 Powered**: Advanced reasoning for financial insights # Basic Source: https://docs.agno.com/agent-os/usage/interfaces/a2a/basic Create a basic AI agent with A2A interface ## Code ```python a2a_basic.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.a2a import A2A chat_agent = Agent( name="Assistant", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a helpful AI assistant.", add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[chat_agent], a2a_interface=True, ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="a2a_basic:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai a2a-protocol ``` ```bash Mac theme={null} python a2a_basic.py ``` ```bash Windows theme={null} python a2a_basic.py ``` ## Key Features * **A2A Interface**: A2A compatible conversation experience * **Real-time Chat**: Instant message exchange * **Markdown Support**: Rich text formatting in responses * **DateTime Context**: Time-aware responses * **Open Protocol**: Compatible with A2A frontends # Research Team Source: https://docs.agno.com/agent-os/usage/interfaces/a2a/team Multi-agent research team with specialized roles and web interface ## Code ```python a2a_research_team.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.a2a import A2A from agno.team import Team researcher = Agent( name="researcher", role="Research Assistant", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a research assistant. Find information and provide detailed analysis.", markdown=True, ) writer = Agent( name="writer", role="Content Writer", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a content writer. Create well-structured content based on research.", markdown=True, ) research_team = Team( members=[researcher, writer], name="research_team", instructions=""" You are a research team that helps users with research and content creation. First, use the researcher to gather information, then use the writer to create content. """, show_members_responses=True, get_member_information_tool=True, add_member_tools_to_context=True, ) # Setup our AgentOS app agent_os = AgentOS( teams=[research_team], a2a_interface=True, ) app = agent_os.get_app() if __name__ == "__main__": """Run our AgentOS. You can see the configuration and available apps at: http://localhost:7777/config """ agent_os.serve(app="a2a_research_team:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai a2a-protocol ``` ```bash Mac theme={null} python a2a_research_team.py ``` ```bash Windows theme={null} python a2a_research_team.py ``` ## Key Features * **Multi-Agent Collaboration**: Researcher and writer working together * **Specialized Roles**: Distinct expertise and responsibilities * **Transparent Process**: See individual agent contributions * **Coordinated Workflow**: Structured research-to-content pipeline * **Web Interface**: Professional team interaction through A2A ## Team Members * **Researcher**: Information gathering and analysis specialist * **Writer**: Content creation and structuring expert * **Workflow**: Sequential collaboration from research to final content # Agent with Tools Source: https://docs.agno.com/agent-os/usage/interfaces/ag-ui/agent-with-tools Investment analyst agent with financial tools and web interface ## Code ```python cookbook/os/interfaces/agui/agent_with_tool.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.agui import AGUI from agno.tools.yfinance import YFinanceTools agent = Agent( model=OpenAIChat(id="gpt-5-mini"), tools=[ YFinanceTools( stock_price=True, analyst_recommendations=True, stock_fundamentals=True ) ], description="You are an investment analyst that researches stock prices, analyst recommendations, and stock fundamentals.", instructions="Format your response using markdown and use tables to display data where possible.", ) agent_os = AgentOS( agents=[agent], interfaces=[AGUI(agent=agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="agent_with_tool:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno yfinance ``` ```bash Mac theme={null} python cookbook/os/interfaces/agui/agent_with_tool.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/agui/agent_with_tool.py ``` ## Key Features * **Financial Data Tools**: Real-time stock prices, analyst recommendations, fundamentals * **Investment Analysis**: Comprehensive company analysis and recommendations * **Data Visualization**: Tables and formatted financial information * **Web Interface**: Professional browser-based interaction * **GPT-4o Powered**: Advanced reasoning for financial insights # Basic Source: https://docs.agno.com/agent-os/usage/interfaces/ag-ui/basic Create a basic AI agent with ChatGPT-like web interface ## Code ```python cookbook/os/interfaces/agui/basic.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.agui import AGUI chat_agent = Agent( name="Assistant", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a helpful AI assistant.", add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[chat_agent], interfaces=[AGUI(agent=chat_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno ag-ui-protocol ``` ```bash Mac theme={null} python cookbook/os/interfaces/agui/basic.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/agui/basic.py ``` ## Key Features * **Web Interface**: ChatGPT-like conversation experience * **Real-time Chat**: Instant message exchange * **Markdown Support**: Rich text formatting in responses * **DateTime Context**: Time-aware responses * **Open Protocol**: Compatible with AG-UI frontends ## Setup Frontend 1. Clone AG-UI repository: `git clone https://github.com/ag-ui-protocol/ag-ui.git` 2. Install dependencies: `cd ag-ui/typescript-sdk && pnpm install` 3. Build integration: `cd integrations/agno && pnpm run build` 4. Start Dojo: `cd ../../apps/dojo && pnpm run dev` 5. Access at [http://localhost:3000](http://localhost:3000) # Research Team Source: https://docs.agno.com/agent-os/usage/interfaces/ag-ui/team Multi-agent research team with specialized roles and web interface ## Code ```python cookbook/os/interfaces/agui/research_team.py theme={null} from agno.agent.agent import Agent from agno.models.openai import OpenAIChat from agno.os.app import AgentOS from agno.os.interfaces.agui.agui import AGUI from agno.team import Team researcher = Agent( name="researcher", role="Research Assistant", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a research assistant. Find information and provide detailed analysis.", markdown=True, ) writer = Agent( name="writer", role="Content Writer", model=OpenAIChat(id="gpt-5-mini"), instructions="You are a content writer. Create well-structured content based on research.", markdown=True, ) research_team = Team( members=[researcher, writer], name="research_team", instructions=""" You are a research team that helps users with research and content creation. First, use the researcher to gather information, then use the writer to create content. """, show_members_responses=True, get_member_information_tool=True, add_member_tools_to_context=True, ) # Setup our AgentOS app agent_os = AgentOS( teams=[research_team], interfaces=[AGUI(team=research_team)], ) app = agent_os.get_app() if __name__ == "__main__": """Run our AgentOS. You can see the configuration and available apps at: http://localhost:7777/config """ agent_os.serve(app="research_team:app", reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/agui/research_team.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/agui/research_team.py ``` ## Key Features * **Multi-Agent Collaboration**: Researcher and writer working together * **Specialized Roles**: Distinct expertise and responsibilities * **Transparent Process**: See individual agent contributions * **Coordinated Workflow**: Structured research-to-content pipeline * **Web Interface**: Professional team interaction through AG-UI ## Team Members * **Researcher**: Information gathering and analysis specialist * **Writer**: Content creation and structuring expert * **Workflow**: Sequential collaboration from research to final content # Slack Agent with User Memory Source: https://docs.agno.com/agent-os/usage/interfaces/slack/agent-with-user-memory Personalized Slack agent that remembers user information and preferences ## Code ```python cookbook/os/interfaces/slack/agent_with_user_memory.py theme={null} from textwrap import dedent from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.memory.manager import MemoryManager from agno.models.anthropic.claude import Claude from agno.os.app import AgentOS from agno.os.interfaces.slack import Slack from agno.tools.duckduckgo import DuckDuckGoTools agent_db = SqliteDb(session_table="agent_sessions", db_file="tmp/persistent_memory.db") memory_manager = MemoryManager( memory_capture_instructions="""\ Collect User's name, Collect Information about user's passion and hobbies, Collect Information about the users likes and dislikes, Collect information about what the user is doing with their life right now """, model=Claude(id="claude-3-5-sonnet-20241022"), ) personal_agent = Agent( name="Basic Agent", model=Claude(id="claude-sonnet-4-20250514"), tools=[DuckDuckGoTools()], add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, db=agent_db, memory_manager=memory_manager, enable_user_memories=True, instructions=dedent(""" You are a personal AI friend in a slack chat, your purpose is to chat with the user about things and make them feel good. First introduce yourself and ask for their name then, ask about themeselves, their hobbies, what they like to do and what they like to talk about. Use the DuckDuckGo tools to find latest infromation about things in the conversations """), debug_mode=True, ) agent_os = AgentOS( agents=[personal_agent], interfaces=[Slack(agent=personal_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="agent_with_user_memory:app", reload=True) ``` ## Usage ```bash theme={null} export SLACK_TOKEN=xoxb-your-bot-user-token export SLACK_SIGNING_SECRET=your-signing-secret export ANTHROPIC_API_KEY=your-anthropic-api-key ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/slack/agent_with_user_memory.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/slack/agent_with_user_memory.py ``` ## Key Features * **Memory Management**: Remembers user names, hobbies, preferences, and activities * **DuckDuckGo Search Integration**: Access to current information during conversations * **Personalized Responses**: Uses stored memories for contextualized replies * **Slack Integration**: Works with direct messages and group conversations * **Claude Powered**: Advanced reasoning and conversation capabilities # Basic Slack Agent Source: https://docs.agno.com/agent-os/usage/interfaces/slack/basic Create a basic AI agent that integrates with Slack for conversations ## Code ```python cookbook/os/interfaces/slack/basic.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.slack import Slack agent_db = SqliteDb(session_table="agent_sessions", db_file="tmp/persistent_memory.db") basic_agent = Agent( name="Basic Agent", model=OpenAIChat(id="gpt-5-mini"), db=agent_db, add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, ) agent_os = AgentOS( agents=[basic_agent], interfaces=[Slack(agent=basic_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", reload=True) ``` ## Usage ```bash theme={null} export SLACK_TOKEN=xoxb-your-bot-user-token export SLACK_SIGNING_SECRET=your-signing-secret export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/slack/basic.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/slack/basic.py ``` ## Key Features * **Slack Integration**: Responds to direct messages and channel mentions * **Conversation History**: Maintains context with last 3 interactions * **Persistent Memory**: SQLite database for session storage * **DateTime Context**: Time-aware responses * **GPT-4o Powered**: Intelligent conversational capabilities # Slack Reasoning Finance Agent Source: https://docs.agno.com/agent-os/usage/interfaces/slack/reasoning-agent Slack agent with advanced reasoning and financial analysis capabilities ## Code ```python cookbook/os/interfaces/slack/reasoning_agent.py theme={null} from agno.agent import Agent from agno.db.sqlite.sqlite import SqliteDb from agno.models.anthropic.claude import Claude from agno.os.app import AgentOS from agno.os.interfaces.slack.slack import Slack from agno.tools.thinking import ThinkingTools from agno.tools.yfinance import YFinanceTools agent_db = SqliteDb(session_table="agent_sessions", db_file="tmp/persistent_memory.db") reasoning_finance_agent = Agent( name="Reasoning Finance Agent", model=Claude(id="claude-3-7-sonnet-latest"), db=agent_db, tools=[ ThinkingTools(add_instructions=True), YFinanceTools( stock_price=True, analyst_recommendations=True, company_info=True, company_news=True, ), ], instructions="Use tables to display data. When you use thinking tools, keep the thinking brief.", add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[reasoning_finance_agent], interfaces=[Slack(agent=reasoning_finance_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="reasoning_agent:app", reload=True) ``` ## Usage ```bash theme={null} export SLACK_TOKEN=xoxb-your-bot-user-token export SLACK_SIGNING_SECRET=your-signing-secret export ANTHROPIC_API_KEY=your-anthropic-api-key ``` ```bash theme={null} pip install -U agno yfinance ``` ```bash Mac theme={null} python cookbook/os/interfaces/slack/reasoning_agent.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/slack/reasoning_agent.py ``` ## Key Features * **Advanced Reasoning**: ThinkingTools for step-by-step financial analysis * **Real-time Data**: Stock prices, analyst recommendations, company news * **Claude Powered**: Superior analytical and reasoning capabilities * **Slack Integration**: Works in channels and direct messages * **Structured Output**: Well-formatted tables and financial insights # Slack Research Workflow Source: https://docs.agno.com/agent-os/usage/interfaces/slack/research-workflow Integrate a research and writing workflow with Slack for structured AI-powered content creation ## Code ```python research_workflow.py theme={null} from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.slack import Slack from agno.tools.duckduckgo import DuckDuckGoTools from agno.workflow.step import Step from agno.workflow.workflow import Workflow workflow_db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Define agents for the workflow researcher_agent = Agent( name="Research Agent", model=OpenAIChat(id="gpt-4o-mini"), tools=[DuckDuckGoTools()], role="Search the web and gather comprehensive research on the given topic", instructions=[ "Search for the most recent and relevant information", "Focus on credible sources and key insights", "Summarize findings clearly and concisely", ], ) writer_agent = Agent( name="Content Writer", model=OpenAIChat(id="gpt-4o-mini"), role="Create engaging content based on research findings", instructions=[ "Write in a clear, engaging, and professional tone", "Structure content with proper headings and bullet points", "Include key insights from the research", "Keep content informative yet accessible", ], ) # Create workflow steps research_step = Step( name="Research Step", agent=researcher_agent, ) writing_step = Step( name="Writing Step", agent=writer_agent, ) # Create the workflow content_workflow = Workflow( name="Content Creation Workflow", description="Research and create content on any topic via Slack", db=workflow_db, steps=[research_step, writing_step], session_id="slack_workflow_session", ) # Create AgentOS with Slack interface for the workflow agent_os = AgentOS( workflows=[content_workflow], interfaces=[Slack(workflow=content_workflow)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="research_workflow:app", reload=True) ``` ## Usage ```bash theme={null} export SLACK_TOKEN=xoxb-your-bot-user-token export SLACK_SIGNING_SECRET=your-signing-secret export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno ddgs psycopg ``` ```bash Mac theme={null} python research_workflow.py ``` ```bash Windows theme={null} python research_workflow.py ``` # WhatsApp Agent with Media Support Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/agent-with-media WhatsApp agent that analyzes images, videos, and audio using multimodal AI ## Code ```python cookbook/os/interfaces/whatsapp/agent_with_media.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.google import Gemini from agno.os.app import AgentOS from agno.os.interfaces.whatsapp import Whatsapp agent_db = SqliteDb(db_file="tmp/persistent_memory.db") media_agent = Agent( name="Media Agent", model=Gemini(id="gemini-2.0-flash"), db=agent_db, add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[media_agent], interfaces=[Whatsapp(agent=media_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="agent_with_media:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export GOOGLE_API_KEY=your_google_api_key export APP_ENV=development ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/agent_with_media.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/agent_with_media.py ``` ## Key Features * **Multimodal AI**: Gemini 2.0 Flash for image, video, and audio processing * **Image Analysis**: Object recognition, scene understanding, text extraction * **Video Processing**: Content analysis and summarization * **Audio Support**: Voice message transcription and response * **Context Integration**: Combines media analysis with conversation history # WhatsApp Agent with User Memory Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/agent-with-user-memory Personalized WhatsApp agent that remembers user information and preferences ## Code ```python cookbook/os/interfaces/whatsapp/agent_with_user_memory.py theme={null} from textwrap import dedent from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.memory.manager import MemoryManager from agno.models.google import Gemini from agno.os.app import AgentOS from agno.os.interfaces.whatsapp import Whatsapp from agno.tools.duckduckgo import DuckDuckGoTools agent_db = SqliteDb(db_file="tmp/persistent_memory.db") memory_manager = MemoryManager( memory_capture_instructions="""\ Collect User's name, Collect Information about user's passion and hobbies, Collect Information about the users likes and dislikes, Collect information about what the user is doing with their life right now """, model=Gemini(id="gemini-2.0-flash"), ) personal_agent = Agent( name="Basic Agent", model=Gemini(id="gemini-2.0-flash"), tools=[DuckDuckGoTools()], add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, db=agent_db, memory_manager=memory_manager, enable_agentic_memory=True, instructions=dedent(""" You are a personal AI friend of the user, your purpose is to chat with the user about things and make them feel good. First introduce yourself and ask for their name then, ask about themeselves, their hobbies, what they like to do and what they like to talk about. Use the DuckDuckGo tools to find latest infromation about things in the conversations """), debug_mode=True, ) agent_os = AgentOS( agents=[personal_agent], interfaces=[Whatsapp(agent=personal_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="agent_with_user_memory:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export APP_ENV=development ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/agent_with_user_memory.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/agent_with_user_memory.py ``` ## Key Features * **Memory Management**: Remembers user names, hobbies, preferences, and activities * **DuckDuckGo Search**: Access to current information during conversations * **Personalized Responses**: Uses stored memories for contextualized replies * **Friendly AI**: Acts as personal AI friend with engaging conversation * **Gemini Powered**: Fast, intelligent responses with multimodal capabilities # Basic WhatsApp Agent Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/basic Create a basic AI agent that integrates with WhatsApp Business API ## Code ```python cookbook/os/interfaces/whatsapp/basic.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.interfaces.whatsapp import Whatsapp agent_db = SqliteDb(db_file="tmp/persistent_memory.db") basic_agent = Agent( name="Basic Agent", model=OpenAIChat(id="gpt-5-mini"), db=agent_db, add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[basic_agent], interfaces=[Whatsapp(agent=basic_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="basic:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export OPENAI_API_KEY=your_openai_api_key export APP_ENV=development ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/basic.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/basic.py ``` ## Key Features * **WhatsApp Integration**: Responds to messages automatically * **Conversation History**: Maintains context with last 3 interactions * **Persistent Memory**: SQLite database for session storage * **DateTime Context**: Time-aware responses * **Markdown Support**: Rich text formatting in messages # WhatsApp Image Generation Agent (Model-based) Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/image-generation-model WhatsApp agent that generates images using Gemini's built-in capabilities ## Code ```python cookbook/os/interfaces/whatsapp/image_generation_model.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.google import Gemini from agno.os.app import AgentOS from agno.os.interfaces.whatsapp import Whatsapp agent_db = SqliteDb(db_file="tmp/persistent_memory.db") image_agent = Agent( id="image_generation_model", db=agent_db, model=Gemini( id="gemini-2.0-flash-exp-image-generation", response_modalities=["Text", "Image"], ), debug_mode=True, ) agent_os = AgentOS( agents=[image_agent], interfaces=[Whatsapp(agent=image_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="image_generation_model:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export GOOGLE_API_KEY=your_google_api_key export APP_ENV=development ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/image_generation_model.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/image_generation_model.py ``` ## Key Features * **Direct Image Generation**: Gemini 2.0 Flash experimental image generation * **Text-to-Image**: Converts descriptions into visual content * **Multimodal Responses**: Generates both text and images * **WhatsApp Integration**: Sends images directly through WhatsApp * **Debug Mode**: Enhanced logging for troubleshooting # WhatsApp Image Generation Agent (Tool-based) Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/image-generation-tools WhatsApp agent that generates images using OpenAI's image generation tools ## Code ```python cookbook/os/interfaces/whatsapp/image_generation_tools.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.openai import OpenAIChat from agno.os.app import AgentOS from agno.os.interfaces.whatsapp import Whatsapp from agno.tools.openai import OpenAITools agent_db = SqliteDb(db_file="tmp/persistent_memory.db") image_agent = Agent( id="image_generation_tools", db=agent_db, model=OpenAIChat(id="gpt-5-mini"), tools=[OpenAITools(image_model="gpt-image-1")], markdown=True, debug_mode=True, add_history_to_context=True, ) agent_os = AgentOS( agents=[image_agent], interfaces=[Whatsapp(agent=image_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="image_generation_tools:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export OPENAI_API_KEY=your_openai_api_key export APP_ENV=development ``` ```bash theme={null} pip install -U agno ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/image_generation_tools.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/image_generation_tools.py ``` ## Key Features * **Tool-based Generation**: OpenAI's GPT Image-1 model via external tools * **High-Quality Images**: Professional-grade image generation * **Conversational Interface**: Natural language interaction for image requests * **History Context**: Remembers previous images and conversations * **GPT-4o Orchestration**: Intelligent conversation and tool management # WhatsApp Reasoning Finance Agent Source: https://docs.agno.com/agent-os/usage/interfaces/whatsapp/reasoning-agent WhatsApp agent with advanced reasoning and financial analysis capabilities ## Code ```python cookbook/os/interfaces/whatsapp/reasoning_agent.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.anthropic.claude import Claude from agno.os.app import AgentOS from agno.os.interfaces.whatsapp import Whatsapp from agno.tools.thinking import ThinkingTools from agno.tools.yfinance import YFinanceTools agent_db = SqliteDb(db_file="tmp/persistent_memory.db") reasoning_finance_agent = Agent( name="Reasoning Finance Agent", model=Claude(id="claude-3-7-sonnet-latest"), db=agent_db, tools=[ ThinkingTools(add_instructions=True), YFinanceTools( stock_price=True, analyst_recommendations=True, company_info=True, company_news=True, ), ], instructions="Use tables to display data. When you use thinking tools, keep the thinking brief.", add_datetime_to_context=True, markdown=True, ) agent_os = AgentOS( agents=[reasoning_finance_agent], interfaces=[Whatsapp(agent=reasoning_finance_agent)], ) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve(app="reasoning_agent:app", reload=True) ``` ## Usage ```bash theme={null} export WHATSAPP_ACCESS_TOKEN=your_whatsapp_access_token export WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id export WHATSAPP_WEBHOOK_URL=your_webhook_url export WHATSAPP_VERIFY_TOKEN=your_verify_token export ANTHROPIC_API_KEY=your_anthropic_api_key export APP_ENV=development ``` ```bash theme={null} pip install -U agno yfinance ``` ```bash Mac theme={null} python cookbook/os/interfaces/whatsapp/reasoning_agent.py ``` ```bash Windows theme={null} python cookbook/os/interfaces/whatsapp/reasoning_agent.py ``` ## Key Features * **Advanced Reasoning**: ThinkingTools for step-by-step financial analysis * **Real-time Data**: Stock prices, analyst recommendations, company news * **Claude Powered**: Superior analytical and reasoning capabilities * **Structured Output**: Well-formatted tables and financial insights * **Market Intelligence**: Comprehensive company analysis and recommendations # Enable AgentOS MCP Source: https://docs.agno.com/agent-os/usage/mcp/enable-mcp-example Complete AgentOS setup with MCP support enabled ## Code ```python cookbook/agent_os/mcp/enable_mcp_example.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.tools.duckduckgo import DuckDuckGoTools # Setup the database db = SqliteDb(db_file="tmp/agentos.db") # Setup basic research agent web_research_agent = Agent( id="web-research-agent", name="Web Research Agent", model=Claude(id="claude-sonnet-4-0"), db=db, tools=[DuckDuckGoTools()], add_history_to_context=True, num_history_runs=3, add_datetime_to_context=True, enable_session_summaries=True, markdown=True, ) # Setup our AgentOS with MCP enabled agent_os = AgentOS( description="Example app with MCP enabled", agents=[web_research_agent], enable_mcp_server=True, # This enables a LLM-friendly MCP server at /mcp ) app = agent_os.get_app() if __name__ == "__main__": """Run your AgentOS. You can see view your LLM-friendly MCP server at: http://localhost:7777/mcp """ agent_os.serve(app="enable_mcp_example:app") ``` ## Define a local test client ```python test_client.py theme={null} import asyncio from agno.agent import Agent from agno.models.anthropic import Claude from agno.tools.mcp import MCPTools # This is the URL of the MCP server we want to use. server_url = "http://localhost:7777/mcp" async def run_agent(message: str) -> None: async with MCPTools(transport="streamable-http", url=server_url) as mcp_tools: agent = Agent( model=Claude(id="claude-sonnet-4-0"), tools=[mcp_tools], markdown=True, ) await agent.aprint_response(input=message, stream=True, markdown=True) # Example usage if __name__ == "__main__": asyncio.run(run_agent("Which agents do I have in my AgentOS?")) ``` ## Usage ```bash theme={null} export ANTHROPIC_API_KEY=your_anthropic_api_key ``` ```bash theme={null} pip install -U agno anthropic fastapi uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash Mac theme={null} python cookbook/agent_os/mcp/enable_mcp_example.py ``` ```bash Windows theme={null} python cookbook/agent_os/mcp/enable_mcp_example.py ``` ```bash Mac theme={null} python cookbook/agent_os/mcp/test_client.py ``` ```bash Windows theme={null} python cookbook/agent_os/mcp/test_client.py ``` # AgentOS with MCPTools Source: https://docs.agno.com/agent-os/usage/mcp/mcp-tools-example Complete AgentOS setup with MCPTools enabled on agents ## Code ```python cookbook/agent_os/mcp/mcp_tools_example.py theme={null} from agno.agent import Agent from agno.db.sqlite import SqliteDb from agno.models.anthropic import Claude from agno.os import AgentOS from agno.tools.mcp import MCPTools # Setup the database db = SqliteDb(db_file="tmp/agentos.db") mcp_tools = MCPTools(transport="streamable-http", url="https://docs.agno.com/mcp") # Setup basic agent agno_support_agent = Agent( id="agno-support-agent", name="Agno Support Agent", model=Claude(id="claude-sonnet-4-0"), db=db, tools=[mcp_tools], add_history_to_context=True, num_history_runs=3, markdown=True, ) agent_os = AgentOS( description="Example app with MCP Tools", agents=[agno_support_agent], ) app = agent_os.get_app() if __name__ == "__main__": """Run your AgentOS. You can see test your AgentOS at: http://localhost:7777/docs """ # Don't use reload=True here, this can cause issues with the lifespan agent_os.serve(app="mcp_tools_example:app") ``` ## Usage ```bash theme={null} export ANTHROPIC_API_KEY=your_anthropic_api_key ``` ```bash theme={null} pip install -U agno anthropic fastapi uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash Mac theme={null} python cookbook/agent_os/mcp/mcp_tools_example.py ``` ```bash Windows theme={null} python cookbook/agent_os/mcp/mcp_tools_example.py ``` # Custom FastAPI App with JWT Middleware Source: https://docs.agno.com/agent-os/usage/middleware/custom-fastapi-jwt Custom FastAPI application with JWT middleware for authentication and AgentOS integration This example demonstrates how to integrate JWT middleware with your custom FastAPI application and then add AgentOS functionality on top. ## Code ```python custom_fastapi_jwt.py theme={null} from datetime import datetime, timedelta, UTC import jwt from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.middleware import JWTMiddleware from agno.tools.duckduckgo import DuckDuckGoTools from fastapi import FastAPI, Form, HTTPException # JWT Secret (use environment variable in production) JWT_SECRET = "a-string-secret-at-least-256-bits-long" # Setup database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Create agent research_agent = Agent( id="research-agent", name="Research Agent", model=OpenAIChat(id="gpt-4o"), db=db, tools=[DuckDuckGoTools()], add_history_to_context=True, markdown=True, ) # Create custom FastAPI app app = FastAPI( title="Example Custom App", version="1.0.0", ) # Add Agno JWT middleware to your custom FastAPI app app.add_middleware( JWTMiddleware, secret_key=JWT_SECRET, excluded_route_paths=[ "/auth/login" ], # We don't want to validate the token for the login endpoint validate=True, # Set validate to False to skip token validation ) # Custom routes that use JWT @app.post("/auth/login") async def login(username: str = Form(...), password: str = Form(...)): """Login endpoint that returns JWT token""" if username == "demo" and password == "password": payload = { "sub": "user_123", "username": username, "exp": datetime.now(UTC) + timedelta(hours=24), "iat": datetime.now(UTC), } token = jwt.encode(payload, JWT_SECRET, algorithm="HS256") return {"access_token": token, "token_type": "bearer"} raise HTTPException(status_code=401, detail="Invalid credentials") # Clean AgentOS setup with tuple middleware pattern! ✨ agent_os = AgentOS( description="JWT Protected AgentOS", agents=[research_agent], base_app=app, ) # Get the final app app = agent_os.get_app() if __name__ == "__main__": """ Run your AgentOS with JWT middleware applied to the entire app. Test endpoints: 1. POST /auth/login - Login to get JWT token 2. GET /config - Protected route (requires JWT) """ agent_os.serve( app="custom_fastapi_jwt:app", port=7777, reload=True ) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai pyjwt ddgs "fastapi[standard]" uvicorn sqlalchemy pgvector psycopg python-multipart ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash theme={null} python custom_fastapi_jwt.py ``` **Step 1: Login to get JWT token** ```bash theme={null} TOKEN=$(curl -X POST "http://localhost:7777/auth/login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=demo&password=password" \ | jq -r '.access_token') echo "Token: $TOKEN" ``` **Step 2: Test protected endpoints with token** ```bash theme={null} # Test AgentOS config endpoint curl -H "Authorization: Bearer $TOKEN" \ "http://localhost:7777/config" # Test agent interaction curl -X POST "http://localhost:7777/agents/research-agent/runs" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"message": "Search for information about FastAPI middleware"}' ``` **Step 3: Test without token (should get 401)** ```bash theme={null} curl "http://localhost:7777/config" # Should return: {"detail": "Not authenticated"} ``` 1. **Visit the API docs**: [http://localhost:7777/docs](http://localhost:7777/docs) 2. **Login via form**: Try the `/auth/login` endpoint with `username=demo` and `password=password` 3. **Copy the token**: From the response, copy the `access_token` value 4. **Authorize in docs**: Click the "Authorize" button and paste `Bearer ` 5. **Test protected endpoints**: Try any AgentOS endpoint - they should now work ## Authentication Flow Client sends credentials to `/auth/login`: ```bash theme={null} POST /auth/login Content-Type: application/x-www-form-urlencoded username=demo&password=password ``` Server validates credentials and returns JWT: ```json theme={null} { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "token_type": "bearer" } ``` Client includes token in Authorization header: ```bash theme={null} Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... ``` JWT middleware validates token and allows/denies access ## Developer Resources * [JWT Middleware Documentation](/agent-os/middleware/jwt) * [Custom FastAPI Documentation](/agent-os/custom-fastapi/overview) * [FastAPI Security Documentation](https://fastapi.tiangolo.com/tutorial/security/) # Custom Middleware Source: https://docs.agno.com/agent-os/usage/middleware/custom-middleware AgentOS with custom middleware for rate limiting, logging, and monitoring This example demonstrates how to create and add custom middleware to your AgentOS application. We implement two common middleware types: rate limiting and request/response logging. ## Code ```python custom_middleware.py theme={null} import time from collections import defaultdict, deque from typing import Dict from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.tools.duckduckgo import DuckDuckGoTools from fastapi import Request, Response from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware # === Rate Limiting Middleware === class RateLimitMiddleware(BaseHTTPMiddleware): """ Rate limiting middleware that limits requests per IP address. """ def __init__(self, app, requests_per_minute: int = 60, window_size: int = 60): super().__init__(app) self.requests_per_minute = requests_per_minute self.window_size = window_size # Store request timestamps per IP self.request_history: Dict[str, deque] = defaultdict(lambda: deque()) async def dispatch(self, request: Request, call_next) -> Response: # Get client IP client_ip = request.client.host if request.client else "unknown" current_time = time.time() # Clean old requests outside the window history = self.request_history[client_ip] while history and current_time - history[0] > self.window_size: history.popleft() # Check if rate limit exceeded if len(history) >= self.requests_per_minute: return JSONResponse( status_code=429, content={ "detail": f"Rate limit exceeded. Max {self.requests_per_minute} requests per minute." }, ) # Add current request to history history.append(current_time) # Add rate limit headers response = await call_next(request) response.headers["X-RateLimit-Limit"] = str(self.requests_per_minute) response.headers["X-RateLimit-Remaining"] = str( self.requests_per_minute - len(history) ) response.headers["X-RateLimit-Reset"] = str( int(current_time + self.window_size) ) return response # === Request/Response Logging Middleware === class RequestLoggingMiddleware(BaseHTTPMiddleware): """ Request/response logging middleware with timing and basic info. """ def __init__(self, app, log_body: bool = False, log_headers: bool = False): super().__init__(app) self.log_body = log_body self.log_headers = log_headers self.request_count = 0 async def dispatch(self, request: Request, call_next) -> Response: self.request_count += 1 start_time = time.time() # Basic request info client_ip = request.client.host if request.client else "unknown" print( f"🔍 Request #{self.request_count}: {request.method} {request.url.path} from {client_ip}" ) # Optional: Log headers if self.log_headers: print(f"📋 Headers: {dict(request.headers)}") # Optional: Log request body if self.log_body and request.method in ["POST", "PUT", "PATCH"]: body = await request.body() if body: print(f"📝 Body: {body.decode()}") # Process request response = await call_next(request) # Log response info duration = time.time() - start_time status_emoji = "✅" if response.status_code < 400 else "❌" print( f"{status_emoji} Response: {response.status_code} in {duration * 1000:.1f}ms" ) # Add request count to response header response.headers["X-Request-Count"] = str(self.request_count) return response # === Setup database and agent === db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") agent = Agent( id="demo-agent", name="Demo Agent", model=OpenAIChat(id="gpt-4o"), db=db, tools=[DuckDuckGoTools()], markdown=True, ) agent_os = AgentOS( description="Essential middleware demo with rate limiting and logging", agents=[agent], ) app = agent_os.get_app() # Add custom middleware app.add_middleware( RateLimitMiddleware, requests_per_minute=10, window_size=60, ) app.add_middleware( RequestLoggingMiddleware, log_body=False, log_headers=False, ) if __name__ == "__main__": """ Run the essential middleware demo using AgentOS serve method. Features: 1. Rate Limiting (10 requests/minute) 2. Request/Response Logging """ agent_os.serve( app="custom_middleware:app", reload=True, ) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai ddgs "fastapi[standard]" uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash theme={null} python custom_middleware.py ``` **Basic Request (observe console logging):** ```bash theme={null} curl http://localhost:7777/config ``` **Test Rate Limiting (trigger 429 errors after 10 requests):** ```bash theme={null} for i in {1..15}; do curl http://localhost:7777/config; done ``` **Check Rate Limit Headers:** ```bash theme={null} curl -v http://localhost:7777/config ``` ## Middleware Features **Prevents API abuse by limiting requests per IP:** * **Configurable Limits**: Set requests per minute and time window * **Per-IP Tracking**: Different limits for different IP addresses * **Sliding Window**: Uses a sliding time window for accurate limiting * **Rate Limit Headers**: Provides client information about limits **Headers Added:** * `X-RateLimit-Limit`: Maximum requests allowed * `X-RateLimit-Remaining`: Requests remaining in current window * `X-RateLimit-Reset`: Timestamp when the window resets **Customization:** ```python theme={null} app.add_middleware( RateLimitMiddleware, requests_per_minute=100, # Allow 100 requests per minute window_size=60, # 60-second sliding window ) ``` **Comprehensive request and response logging:** * **Request Details**: Method, path, client IP, timing * **Response Tracking**: Status codes, response time * **Optional Body Logging**: Log request bodies for debugging * **Optional Header Logging**: Log request headers * **Request Counter**: Track total requests processed **Console Output Example:** ``` 🔍 Request #1: GET /config from 127.0.0.1 ✅ Response: 200 in 45.2ms 🔍 Request #2: POST /agents/demo-agent/runs from 127.0.0.1 ✅ Response: 200 in 1240.8ms ``` **Customization:** ```python theme={null} app.add_middleware( RequestLoggingMiddleware, log_body=True, # Log request bodies log_headers=True, # Log request headers ) ``` ## Developer Resources * [Custom Middleware Documentation](/agent-os/middleware/custom) * [FastAPI Middleware Documentation](https://fastapi.tiangolo.com/tutorial/middleware/) # JWT Middleware with Cookies Source: https://docs.agno.com/agent-os/usage/middleware/jwt-cookies AgentOS with JWT middleware using HTTP-only cookies for secure web authentication This example demonstrates how to use JWT middleware with AgentOS using HTTP-only cookies instead of Authorization headers. This approach is more secure for web applications as it prevents XSS attacks. ## Code ```python jwt_cookies.py theme={null} from datetime import UTC, datetime, timedelta import jwt from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.middleware import JWTMiddleware from agno.os.middleware.jwt import TokenSource from fastapi import FastAPI, Response # JWT Secret (use environment variable in production) JWT_SECRET = "a-string-secret-at-least-256-bits-long" # Setup database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") def get_user_profile(dependencies: dict) -> dict: """ Get the current user's profile. """ return { "name": dependencies.get("name", "Unknown"), "email": dependencies.get("email", "Unknown"), "roles": dependencies.get("roles", []), "organization": dependencies.get("org", "Unknown"), } # Create agent profile_agent = Agent( id="profile-agent", name="Profile Agent", model=OpenAIChat(id="gpt-4o"), db=db, tools=[get_user_profile], instructions="You are a profile agent. You can search for information and access user profiles.", add_history_to_context=True, markdown=True, ) app = FastAPI() # Add a simple endpoint to set the JWT authentication cookie @app.get("/set-auth-cookie") async def set_auth_cookie(response: Response): """ Endpoint to set the JWT authentication cookie. In a real application, this would be done after successful login. """ # Create a test JWT token payload = { "sub": "cookie_user_789", "session_id": "cookie_session_123", "name": "Jane Smith", "email": "jane.smith@example.com", "roles": ["user", "premium"], "org": "Example Corp", "exp": datetime.now(UTC) + timedelta(hours=24), "iat": datetime.now(UTC), } token = jwt.encode(payload, JWT_SECRET, algorithm="HS256") # Set HTTP-only cookie (more secure than localStorage for JWT storage) response.set_cookie( key="auth_token", value=token, httponly=True, # Prevents access from JavaScript (XSS protection) secure=True, # Only send over HTTPS in production samesite="strict", # CSRF protection max_age=24 * 60 * 60, # 24 hours ) return { "message": "Authentication cookie set successfully", "cookie_name": "auth_token", "expires_in": "24 hours", "security_features": ["httponly", "secure", "samesite=strict"], "instructions": "Now you can make authenticated requests without Authorization headers", } # Add a simple endpoint to clear the JWT authentication cookie @app.get("/clear-auth-cookie") async def clear_auth_cookie(response: Response): """Endpoint to clear the JWT authentication cookie (logout).""" response.delete_cookie(key="auth_token") return {"message": "Authentication cookie cleared successfully"} # Add JWT middleware configured for cookie-based authentication app.add_middleware( JWTMiddleware, secret_key=JWT_SECRET, # or use JWT_SECRET_KEY environment variable algorithm="HS256", excluded_route_paths=[ "/set-auth-cookie", "/clear-auth-cookie", ], token_source=TokenSource.COOKIE, # Extract JWT from cookies cookie_name="auth_token", # Name of the cookie containing the JWT user_id_claim="sub", # Extract user_id from 'sub' claim session_id_claim="session_id", # Extract session_id from 'session_id' claim dependencies_claims=[ "name", "email", "roles", "org", ], # Additional claims to extract validate=True, # We want to ensure the token is valid ) agent_os = AgentOS( description="JWT Cookie-Based AgentOS", agents=[profile_agent], base_app=app, ) # Get the final app app = agent_os.get_app() if __name__ == "__main__": """ Run your AgentOS with JWT cookie authentication. """ agent_os.serve( app="jwt_cookies:app", port=7777, reload=True ) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai pyjwt "fastapi[standard]" uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash theme={null} python jwt_cookies.py ``` **Step 1: Set the authentication cookie** ```bash theme={null} curl --location 'http://localhost:7777/set-auth-cookie' ``` **Step 2: Make authenticated requests using the cookie** ```bash theme={null} curl --location 'http://localhost:7777/agents/profile-agent/runs' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'message=What do you know about me?' ``` **Step 3: Test browser-based authentication** 1. Visit [http://localhost:7777/set-auth-cookie](http://localhost:7777/set-auth-cookie) in your browser 2. Visit [http://localhost:7777/docs](http://localhost:7777/docs) to see the API documentation 3. Use the "Try it out" feature - cookies are automatically included **Step 4: Clear authentication (logout)** ```bash theme={null} curl --location 'http://localhost:7777/clear-auth-cookie' ``` ## How It Works 1. **Cookie Management**: Custom endpoints handle setting and clearing authentication cookies 2. **JWT Middleware**: Configured to extract tokens from the `auth_token` cookie 3. **Token Validation**: Full validation enabled to ensure security 4. **Parameter Injection**: User profile data automatically injected into agent tools 5. **Route Exclusion**: Cookie management endpoints excluded from authentication ## Cookie vs Header Authentication | Feature | HTTP-Only Cookies | Authorization Headers | | ------------------- | ---------------------------- | -------------------------------------- | | **XSS Protection** | ✅ Protected | ❌ Vulnerable if stored in localStorage | | **CSRF Protection** | ✅ With SameSite flag | ✅ Not sent automatically | | **Mobile Apps** | ❌ Limited support | ✅ Easy to implement | | **Web Apps** | ✅ Automatic handling | ❌ Manual header management | | **Server Setup** | ❌ Requires cookie management | ✅ Stateless | ## Developer Resources * [JWT Middleware Documentation](/agent-os/middleware/jwt) * [JWT Authorization Headers Example](/agent-os/usage/middleware/jwt-middleware) * [Custom FastAPI with JWT](/agent-os/usage/middleware/custom-fastapi-jwt) # JWT Middleware with Authorization Headers Source: https://docs.agno.com/agent-os/usage/middleware/jwt-middleware Complete AgentOS setup with JWT middleware for authentication and parameter injection using Authorization headers This example demonstrates how to use JWT middleware with AgentOS for authentication and automatic parameter injection using Authorization headers. ## Code ```python jwt_middleware.py theme={null} from datetime import UTC, datetime, timedelta import jwt from agno.agent import Agent from agno.db.postgres import PostgresDb from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.os.middleware import JWTMiddleware # JWT Secret (use environment variable in production) JWT_SECRET = "a-string-secret-at-least-256-bits-long" # Setup database db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai") # Define a tool that uses dependencies claims def get_user_details(dependencies: dict): """ Get the current user's details. """ return { "name": dependencies.get("name"), "email": dependencies.get("email"), "roles": dependencies.get("roles"), } # Create agent research_agent = Agent( id="user-agent", model=OpenAIChat(id="gpt-5-mini"), db=db, tools=[get_user_details], instructions="You are a user agent that can get user details if the user asks for them.", ) agent_os = AgentOS( description="JWT Protected AgentOS", agents=[research_agent], ) # Get the final app app = agent_os.get_app() # Add JWT middleware to the app # This middleware will automatically inject JWT values into request.state and is used in the relevant endpoints. app.add_middleware( JWTMiddleware, secret_key=JWT_SECRET, # or use JWT_SECRET_KEY environment variable algorithm="HS256", user_id_claim="sub", # Extract user_id from 'sub' claim session_id_claim="session_id", # Extract session_id from 'session_id' claim dependencies_claims=["name", "email", "roles"], # In this example, we want this middleware to demonstrate parameter injection, not token validation. # In production scenarios, you will probably also want token validation. Be careful setting this to False. validate=False, ) if __name__ == "__main__": """ Run your AgentOS with JWT parameter injection. Test by calling /agents/user-agent/runs with a message: "What do you know about me?" """ # Test token with user_id and session_id: payload = { "sub": "user_123", # This will be injected as user_id parameter "session_id": "demo_session_456", # This will be injected as session_id parameter "exp": datetime.now(UTC) + timedelta(hours=24), "iat": datetime.now(UTC), # Dependency claims "name": "John Doe", "email": "john.doe@example.com", "roles": ["admin", "user"], } token = jwt.encode(payload, JWT_SECRET, algorithm="HS256") print("Test token:") print(token) agent_os.serve(app="jwt_middleware:app", port=7777, reload=True) ``` ## Usage ```bash theme={null} export OPENAI_API_KEY=your_openai_api_key ``` ```bash theme={null} pip install -U agno openai pyjwt "fastapi[standard]" uvicorn sqlalchemy pgvector psycopg ``` ```bash theme={null} # Using Docker docker run -d \ --name agno-postgres \ -e POSTGRES_DB=ai \ -e POSTGRES_USER=ai \ -e POSTGRES_PASSWORD=ai \ -p 5532:5432 \ pgvector/pgvector:pg17 ``` ```bash theme={null} python jwt_middleware.py ``` The server will start and print a test JWT token to the console. **Test with the generated token:** ```bash theme={null} # Use the token printed in the console export TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." curl --location 'http://localhost:7777/agents/user-agent/runs' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --header 'Authorization: Bearer $TOKEN' \ --data-urlencode 'message=What do you know about me?' ``` **Test without token (should still work validate=False):** ```bash theme={null} curl --location 'http://localhost:7777/agents/user-agent/runs' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'message=What do you know about me?' ``` **Check the AgentOS API docs:** Visit [http://localhost:7777/docs](http://localhost:7777/docs) to see all available endpoints. ## How It Works 1. **JWT Generation**: The example creates a test JWT token with user claims 2. **Middleware Setup**: JWT middleware extracts claims from the `Authorization: Bearer ` header 3. **Parameter Injection**: The middleware automatically injects: * `user_id` from the `sub` claim * `session_id` from the `session_id` claim * `dependencies` dict with name, email, and roles 4. **Agent Tools**: The agent can access user details through the injected dependencies ## Next Steps * [JWT Middleware with Cookies](/agent-os/usage/middleware/jwt-cookies) * [Custom FastAPI with JWT](/agent-os/usage/middleware/custom-fastapi-jwt) * [JWT Middleware Documentation](/agent-os/middleware/jwt) # AgentUI Source: https://docs.agno.com/basics/agent-ui/overview An Open Source AgentUI for your AgentOS Agno provides a beautiful UI for interacting with your agents, completely open source, free to use and build on top of. It's a simple interface that allows you to chat with your agents, view their memory, knowledge, and more. The AgentOS only uses data in your database. No data is sent to Agno. Built with Next.js and TypeScript, the Open Source Agent UI was developed in response to community requests for a self-hosted alternative following the success of [AgentOS](https://github.com/agent-os/introduction). ## Get Started with Agent UI To clone the Agent UI, run the following command in your terminal: ```bash theme={null} npx create-agent-ui@latest ``` Enter `y` to create a new project, install dependencies, then run the agent-ui using: ```bash theme={null} cd agent-ui && npm run dev ``` Open [http://localhost:3000](http://localhost:3000) to view the Agent UI, but remember to connect to your local agents.
You can also clone the repository manually ```bash theme={null} git clone https://github.com/agno-agi/agent-ui.git ``` And run the agent-ui using ```bash theme={null} cd agent-ui && pnpm install && pnpm dev ``` ## Connect your AgentOS The Agent UI needs to connect to a AgentOS server, which you can run locally or on any cloud provider. Let's start with a local AgentOS server. Create a file `agentos.py` ```python agentos.py theme={null} from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.os import AgentOS from agno.db.sqlite import SqliteDb from agno.tools.duckduckgo import DuckDuckGoTools from agno.tools.yfinance import YFinanceTools agent_storage: str = "tmp/agents.db" web_agent = Agent( name="Web Agent", model=OpenAIChat(id="gpt-5-mini"), tools=[DuckDuckGoTools()], instructions=["Always include sources"], # Store the agent sessions in a sqlite database db=SqliteDb(db_file=agent_storage), # Adds the current date and time to the context add_datetime_to_context=True, # Adds the history of the conversation to the messages add_history_to_context=True, # Number of history responses to add to the messages num_history_runs=5, # Adds markdown formatting to the messages markdown=True, ) finance_agent = Agent( name="Finance Agent", model=OpenAIChat(id="gpt-5-mini"), tools=[YFinanceTools()], instructions=["Always use tables to display data"], db=SqliteDb(db_file=agent_storage), add_datetime_to_context=True, add_history_to_context=True, num_history_runs=5, markdown=True, ) agent_os = AgentOS(agents=[web_agent, finance_agent]) app = agent_os.get_app() if __name__ == "__main__": agent_os.serve("agentos:app", reload=True) ``` In another terminal, run the AgentOS server: ```bash Mac theme={null} python3 -m venv .venv source .venv/bin/activate ``` ```bash Windows theme={null} python3 -m venv aienv aienv/scripts/activate ``` ```bash Mac theme={null} pip install -U openai ddgs yfinance sqlalchemy 'fastapi[standard]' agno ``` ```bash Windows theme={null} pip install -U openai ddgs yfinance sqlalchemy 'fastapi[standard]' agno ``` ```bash Mac theme={null} export OPENAI_API_KEY=sk-*** ``` ```bash Windows theme={null} setx OPENAI_API_KEY sk-*** ``` ```shell theme={null} python agentos.py ``` Make sure the module path in `agent_os.serve()` matches your filename (e.g., `"agentos:app"` for `agentos.py`). ## View the AgentUI * Open [http://localhost:3000](http://localhost:3000) to view the Agent UI * Enter the `localhost:7777` endpoint on the left sidebar and start chatting with your agents and teams!