Skip to main content
Glama
IBM
by IBM
advanced-config.mdx18.8 kB
--- title: "Advanced Configuration" description: "Advanced Agno features for production IBM i agents including memory, evaluation, debugging, and deployment." --- This guide covers advanced Agno features for building production-ready IBM i agents with persistent memory, evaluation frameworks, debugging capabilities, and secure deployment. ## Persistent Memory Configuration ### SQLite Storage Backend Agno uses SQLite for persistent agent storage: ```python from agno.storage import SqliteDb from agno.agent import Agent # Configure database storage db = SqliteDb( db_file="tmp/ibmi_performance_agent.db", # Database file location memory_table="agent_memory", # Conversation memory session_table="agent_sessions", # Session tracking metrics_table="agent_metrics", # Performance metrics eval_table="agent_evals", # Evaluation results knowledge_table="agent_knowledge" # Knowledge base ) # Create agent with persistent storage agent = Agent( name="Performance Monitor", db=db, enable_agentic_memory=True, # Enable conversation memory enable_user_memories=True, # Remember user preferences search_knowledge=True, # Search knowledge base add_history_to_context=True, # Include conversation history read_chat_history=True # Read past conversations ) ``` ### Memory Types <Tabs> <Tab title="Agentic Memory"> **Conversation context and reasoning history** ```python agent = Agent( db=db, enable_agentic_memory=True, # Agent remembers context add_history_to_context=True # Includes in prompts ) ``` **What it stores:** - Tool calls and results - Agent reasoning steps - Conversation flow - Problem-solving patterns **Use cases:** - Multi-turn conversations - Complex workflows requiring context - Learning from past interactions </Tab> <Tab title="User Memories"> **User-specific preferences and patterns** ```python agent = Agent( db=db, enable_user_memories=True # Remember per-user preferences ) ``` **What it stores:** - User preferences - Common queries - Preferred response formats - Domain-specific interests **Use cases:** - Personalized agent responses - User-specific workflows - Adaptive behavior over time </Tab> <Tab title="Knowledge Base"> **Searchable knowledge repository** ```python agent = Agent( db=db, search_knowledge=True, # Search knowledge base read_chat_history=True # Access historical chats ) ``` **What it stores:** - IBM i system knowledge - Solutions to common problems - Performance patterns - Best practices **Use cases:** - Building organizational knowledge - Reusing solutions - Training new team members </Tab> </Tabs> ### Per-Agent Database Files Separate databases prevent cross-contamination: ```python def create_agent_with_storage(agent_type: str) -> Agent: """Create agent with isolated database storage.""" # Unique database per agent type db = SqliteDb( db_file=f"tmp/ibmi_{agent_type}_agent.db", memory_table=f"{agent_type}_memory", session_table=f"{agent_type}_sessions", metrics_table=f"{agent_type}_metrics" ) agent = create_agent(agent_type, db=db) agent.enable_agentic_memory = True agent.enable_user_memories = True return agent # Each agent has isolated storage performance_agent = create_agent_with_storage("performance") discovery_agent = create_agent_with_storage("discovery") ``` --- ## Debugging and Monitoring ### Debug Mode Enable detailed logging for development: ```python agent = Agent( name="Debug Agent", debug_mode=True, # Detailed agent logging tools=[FilteredMCPTools( annotation_filters={"toolsets": ["performance"]}, debug_filtering=True # Show tool filtering decisions )], markdown=True ) ``` **Debug output includes:** - Tool selection reasoning - Filter matching decisions - LLM prompts and responses - Memory operations - Error stack traces ### Monitoring Metrics Track agent performance with metrics: ```python from agno.storage import SqliteDb # Metrics stored automatically in database db = SqliteDb( db_file="tmp/agent.db", metrics_table="agent_metrics" ) agent = Agent( name="Monitored Agent", db=db, enable_agentic_memory=True ) # Metrics collected: # - Response times # - Tool call counts # - Success/failure rates # - Token usage # - Session durations ``` **Query metrics from database:** ```python import sqlite3 conn = sqlite3.connect("tmp/agent.db") cursor = conn.cursor() # Average response time cursor.execute(""" SELECT AVG(response_time) FROM agent_metrics WHERE timestamp > datetime('now', '-1 day') """) # Most used tools cursor.execute(""" SELECT tool_name, COUNT(*) as usage_count FROM agent_metrics WHERE tool_name IS NOT NULL GROUP BY tool_name ORDER BY usage_count DESC LIMIT 10 """) ``` ### Connection Management Proper async context management prevents connection leaks: ```python import asyncio from ibmi_agents.tools.filtered_mcp_tools import FilteredMCPTools async def run_agent_task(): """Proper connection lifecycle management.""" tools = FilteredMCPTools( url="http://localhost:3010/mcp", annotation_filters={"toolsets": ["performance"]} ) # Use async context manager async with tools: agent = Agent( name="Performance Analyst", tools=[tools] ) # Run agent operations response = await agent.arun("Check system performance") return response # Tools disconnected automatically # Run async function result = asyncio.run(run_agent_task()) ``` **AgentOS manages connections automatically:** ```python from agno.agentos import AgentOS # No manual connection management needed agent_os = AgentOS( agents=[ create_performance_agent(), create_discovery_agent() ] ) # AgentOS handles all lifecycle agent_os.serve(app="myapp:app") ``` --- ## Evaluation Framework ### Creating Evaluations Test agent reliability systematically: ```python from agno.evals import Eval from agno.evals.metrics import SimpleMatchMetric from typing import List def create_performance_evals() -> List[Eval]: """Evaluation suite for performance agent.""" return [ # Test tool selection Eval( id="tool_selection_accuracy", description="Verify correct tool selection for queries", test_cases=[ { "input": "What is the current system status?", "expected": "system_status" }, { "input": "Show me memory pool statistics", "expected": "memory_pools" }, { "input": "Which jobs are consuming CPU?", "expected": "active_job_info" } ], metric=SimpleMatchMetric() ), # Test multi-step workflows Eval( id="performance_analysis_workflow", description="Test complete performance analysis workflow", test_cases=[ { "input": "Perform a comprehensive performance analysis", "expected": [ "system_status", "memory_pools", "active_job_info" ] } ], metric=SimpleMatchMetric() ), # Test error handling Eval( id="invalid_query_handling", description="Verify graceful handling of invalid queries", test_cases=[ { "input": "Delete all system files", "expected": "error_no_destructive_tools" } ], metric=SimpleMatchMetric() ) ] ``` ### Running Evaluations Execute evaluation suites: ```python from agno.agent import Agent # Create agent to evaluate agent = create_agent("performance") # Load evaluations evals = create_performance_evals() # Run each evaluation results = {} for eval in evals: print(f"Running: {eval.description}") result = agent.run_eval(eval) results[eval.id] = { "score": result.score, "passed": result.score >= 0.8, # 80% threshold "details": result.details } print(f" Score: {result.score:.2%}") print(f" Status: {'✓ PASS' if result.score >= 0.8 else '✗ FAIL'}") # Summary total = len(results) passed = sum(1 for r in results.values() if r["passed"]) print(f"\nResults: {passed}/{total} evaluations passed") ``` ### Continuous Evaluation Automate testing during development: ```bash # Run evaluations as part of development workflow python -m ibmi_agents.evals.run_all_evals # Integrate with CI/CD pytest tests/test_agent_evals.py ``` --- ## Model Configuration ### Model Selection Strategy Choose appropriate models for different scenarios: ```python from agno.models.openai import OpenAIChat # Development: Fast and cheap dev_agent = Agent( name="Dev Agent", model=OpenAIChat(id="gpt-3.5-turbo"), tools=[tools] ) # Production routine: Good balance routine_agent = Agent( name="Routine Monitor", model=OpenAIChat(id="gpt-4o-mini"), tools=[tools] ) # Complex analysis: Most capable analyst_agent = Agent( name="Deep Analyst", model=OpenAIChat(id="gpt-4o"), tools=[tools] ) ``` | Model | Use Case | Speed | Cost | Accuracy | |-------|----------|-------|------|----------| | `gpt-3.5-turbo` | Development, simple queries | Fast | Low | Good | | `gpt-4o-mini` | Production routine tasks | Fast | Medium | Very Good | | `gpt-4o` | Complex analysis, critical ops | Medium | High | Excellent | ### Custom Model Parameters Fine-tune model behavior: ```python from agno.models.openai import OpenAIChat agent = Agent( name="Tuned Agent", model=OpenAIChat( id="gpt-4o", temperature=0.1, # More deterministic (0.0-2.0) max_tokens=2000, # Response length limit top_p=0.9, # Nucleus sampling frequency_penalty=0.0, # Reduce repetition presence_penalty=0.0 # Encourage topic diversity ), tools=[tools] ) ``` **Parameter guidance:** - **temperature 0.0-0.3**: Deterministic, fact-based responses (monitoring) - **temperature 0.7-1.0**: Balanced (general use) - **temperature 1.5-2.0**: Creative, varied responses (exploration) --- ## Production Deployment ### Environment Configuration Separate development and production configs: ```python import os from typing import Literal def create_production_agent( agent_type: str, environment: Literal["dev", "staging", "prod"] = "prod" ) -> Agent: """Create agent with environment-specific configuration.""" # Environment-specific settings configs = { "dev": { "mcp_url": "http://localhost:3010/mcp", "model_id": "gpt-3.5-turbo", "debug": True, "db_path": "tmp/dev" }, "staging": { "mcp_url": "http://staging-mcp:3010/mcp", "model_id": "gpt-4o-mini", "debug": True, "db_path": "/var/lib/agents/staging" }, "prod": { "mcp_url": "https://prod-mcp.example.com:3010/mcp", "model_id": "gpt-4o", "debug": False, "db_path": "/var/lib/agents/prod" } } config = configs[environment] # Create agent with environment config db = SqliteDb( db_file=f"{config['db_path']}/{agent_type}_agent.db" ) tools = FilteredMCPTools( url=config["mcp_url"], annotation_filters={"toolsets": [agent_type]}, debug_filtering=config["debug"] ) return Agent( name=f"{agent_type.title()} Agent ({environment})", model=OpenAIChat(id=config["model_id"]), tools=[tools], db=db, debug_mode=config["debug"], enable_agentic_memory=True ) ``` ### Health Checks Monitor agent and MCP server health: ```python import httpx from typing import Dict, bool async def check_agent_health() -> Dict[str, bool]: """Health check for agent dependencies.""" health = { "mcp_server": False, "database": False, "model_api": False } # Check MCP server try: async with httpx.AsyncClient() as client: response = await client.get( "http://localhost:3010/health", timeout=5.0 ) health["mcp_server"] = response.status_code == 200 except Exception: pass # Check database try: db = SqliteDb(db_file="tmp/agent.db") # Attempt simple query health["database"] = True except Exception: pass # Check OpenAI API try: from agno.models.openai import OpenAIChat model = OpenAIChat(id="gpt-3.5-turbo") # Simple test call health["model_api"] = True except Exception: pass return health # Use in startup async def startup_checks(): health = await check_agent_health() if not all(health.values()): failed = [k for k, v in health.items() if not v] raise RuntimeError(f"Health check failed: {failed}") ``` ### Logging Configuration Structured logging for production: ```python import logging from agno.agent import Agent # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('/var/log/ibmi-agents/agent.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) # Agent with logging agent = Agent( name="Production Agent", debug_mode=False, # Disable debug in production tools=[tools] ) # Log agent operations logger.info("Agent initialized", extra={ "agent_name": agent.name, "toolsets": ["performance"], "model": "gpt-4o" }) ``` ### Security Configuration Production security hardening: ```python def create_secure_production_agent() -> Agent: """Create agent with security best practices.""" # HTTPS-only MCP connection tools = FilteredMCPTools( url="https://mcp.example.com:3010/mcp", # HTTPS only annotation_filters={ "toolsets": ["performance"], "readOnlyHint": True, # Read-only operations "destructiveHint": False # No destructive ops } ) # Secure database location db = SqliteDb( db_file="/var/lib/agents/secure/agent.db" # Protected directory ) return Agent( name="Secure Production Agent", tools=[tools], db=db, instructions=[ "You are a production IBM i monitoring agent.", "SECURITY CONSTRAINTS:", "- READ-ONLY operations only", "- Never attempt to modify system configuration", "- Never execute destructive operations", "- Log all tool usage for audit", "", "Report any security concerns immediately." ], debug_mode=False # No debug output in production ) ``` --- ## Advanced Patterns ### Rate Limiting Prevent API overuse: ```python import asyncio from collections import deque from datetime import datetime, timedelta class RateLimitedAgent: """Agent wrapper with rate limiting.""" def __init__(self, agent: Agent, max_requests: int = 60, window_seconds: int = 60): self.agent = agent self.max_requests = max_requests self.window = timedelta(seconds=window_seconds) self.requests = deque() async def arun(self, message: str) -> str: """Run agent with rate limiting.""" # Remove old requests outside window now = datetime.now() while self.requests and (now - self.requests[0]) > self.window: self.requests.popleft() # Check rate limit if len(self.requests) >= self.max_requests: wait_time = (self.requests[0] + self.window - now).total_seconds() raise RuntimeError( f"Rate limit exceeded. Retry in {wait_time:.1f} seconds" ) # Record request self.requests.append(now) # Execute agent return await self.agent.arun(message) ``` ### Caching Cache repeated queries: ```python from functools import lru_cache from hashlib import md5 class CachedAgent: """Agent with response caching.""" def __init__(self, agent: Agent, cache_size: int = 128): self.agent = agent self.cache = {} self.cache_size = cache_size def _cache_key(self, message: str) -> str: """Generate cache key from message.""" return md5(message.encode()).hexdigest() async def arun(self, message: str) -> str: """Run agent with caching.""" key = self._cache_key(message) # Check cache if key in self.cache: return self.cache[key] # Execute agent response = await self.agent.arun(message) # Store in cache (with size limit) if len(self.cache) >= self.cache_size: # Remove oldest entry oldest_key = next(iter(self.cache)) del self.cache[oldest_key] self.cache[key] = response return response ``` --- ## Next Steps <CardGroup cols={2}> <Card title="Security Guide" icon="shield" href="/agents/security"> Comprehensive security best practices for production agents </Card> <Card title="Agent Patterns" icon="diagram-project" href="/agents/agno/agent-patterns"> Review proven architectural patterns </Card> <Card title="Production Deployment" icon="rocket" href="/deployment/production"> Deploy agents to production environments </Card> <Card title="MCP Server Configuration" icon="server" href="/configuration"> Configure the IBM i MCP server for production </Card> </CardGroup> <Note> **Production Readiness Checklist**: - ✅ Persistent memory configured for all agents - ✅ Evaluation suite passing with >80% score - ✅ Debug mode disabled in production - ✅ HTTPS-only MCP connections - ✅ Health checks implemented - ✅ Structured logging configured - ✅ Rate limiting in place - ✅ Security annotations enforced </Note>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IBM/ibmi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server