Skip to main content

Overview

Follow these best practices to get the most out of Agentflare while ensuring optimal performance, security, and reliability.

Performance Optimization

Connection Management

Connection Pooling

Enable connection pooling for better performance

Keep-Alive

Use persistent connections to reduce latency
// Optimal connection configuration
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { HTTPTransport } from "@modelcontextprotocol/sdk/client/http.js";

const client = new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    },
    // Connection options
    timeout: 30000,           // 30 second timeout
    keepAlive: true,          // Enable persistent connections
  })
});

Batching and Sampling

For high-volume applications, Agentflare automatically handles batching and sampling on the server side. Configure these settings in your dashboard:
  • Sampling Rate: Adjust in Dashboard → Settings → Observability
  • Smart Sampling: Automatically enabled (prioritizes errors and slow calls)
  • Batching: Handled automatically by the proxy

Caching Strategy

Agentflare provides intelligent caching at the proxy level. Configure caching in your dashboard:
  • Metadata Caching: Tool schemas and server info (5-minute TTL)
  • Response Caching: Deterministic tool responses (configurable per tool)
  • Cache Invalidation: Automatic on schema changes

Security Best Practices

API Key Management

Never commit API keys to version control or expose them in client-side code.
1

Environment Variables

Store API keys in environment variables
# .env file (never commit this)
API_JWT_SECRET=your_jwt_secret_here
AGENTFLARE_PROJECT_ID=proj_abc123
2

Key Rotation

Rotate API keys regularly
// Set up key rotation reminder
const client = new Client({
transport: new HTTPTransport({
baseUrl: process.env.AGENTFLARE_PROXY_URL,
headers: {
  "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
}
  apiKey: process.env.API_JWT_SECRET,
  keyRotationWarning: true,  // Warn before key expires
  keyRotationDays: 30        // Rotate every 30 days
});
3

Scope Limitation

Use the minimum required scopes
// Create keys with specific scopes in dashboard
const scopes = [
  'tools:read',     // Read tool call data
  'servers:read',   // Read server configurations
  'analytics:read'  // Read analytics data
  // Avoid 'admin' or 'write' scopes unless necessary
];
4

Network Security

Restrict network access when possible
const client = new Client({
transport: new HTTPTransport({
baseUrl: process.env.AGENTFLARE_PROXY_URL,
headers: {
  "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
}
  apiKey: process.env.API_JWT_SECRET,
  allowedIPs: ['192.168.1.0/24'],  // Restrict to specific networks
  requireTLS: true,                 // Enforce TLS 1.3
  verifyCertificates: true         // Verify SSL certificates
});

Double Authentication

For highly sensitive environments, implement double authentication:
// Primary authentication (Agentflare)
const client = new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    }
  apiKey: process.env.API_JWT_SECRET,
  projectId: process.env.AGENTFLARE_PROJECT_ID
});

// Secondary authentication (Your MCP servers)
const servers = [{
  name: "secure-server",
  endpoint: "https://secure.yourcompany.com/mcp",
  authentication: {
    type: "bearer",
    token: process.env.YOUR_SERVER_TOKEN,
    headers: {
      "X-Client-ID": "agentflare-telepathy",
      "X-Request-Signature": computeSignature(request)
    }
  }
}];

Reliability and Error Handling

Comprehensive Error Handling

// Standard error handling with try/catch

async function robustToolCall(client, toolName, args, options = {}) {
  const maxRetries = options.maxRetries || 3;
  const retryDelay = options.retryDelay || 1000;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await client.callTool({
        name: toolName,
        arguments: args,
        timeout: options.timeout || 30000,
        metadata: {
          attempt: attempt,
          maxRetries: maxRetries,
          reasoning: options.reasoning || `Calling ${toolName}`
        }
      });
      
      return result;
      
    } catch (error) {
      if (error instanceof NetworkError && attempt < maxRetries) {
        console.warn(`Network error on attempt ${attempt}, retrying...`);
        await new Promise(resolve => setTimeout(resolve, retryDelay * attempt));
        continue;
      }
      
      if (error instanceof ToolCallError) {
        console.error(`Tool call failed: ${error.message}`, {
          tool: toolName,
          arguments: args,
          error: error.details
        });
        throw error;
      }
      
      // Re-throw for unexpected errors
      throw error;
    }
  }
}

Circuit Breaker Pattern

class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.failureThreshold = threshold;
    this.timeout = timeout;
    this.failureCount = 0;
    this.lastFailureTime = null;
    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
  }
  
  async call(fn) {
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailureTime < this.timeout) {
        throw new Error('Circuit breaker is OPEN');
      }
      this.state = 'HALF_OPEN';
    }
    
    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }
  
  onSuccess() {
    this.failureCount = 0;
    this.state = 'CLOSED';
  }
  
  onFailure() {
    this.failureCount++;
    this.lastFailureTime = Date.now();
    
    if (this.failureCount >= this.failureThreshold) {
      this.state = 'OPEN';
    }
  }
}

// Usage
const circuitBreaker = new CircuitBreaker(5, 60000);

async function protectedToolCall(client, toolName, args) {
  return circuitBreaker.call(() => 
    client.callTool({ name: toolName, arguments: args })
  );
}

Health Monitoring

// Add health checks to your application
class HealthMonitor {
  constructor(client) {
    this.client = client;
    this.healthy = true;
    this.lastCheck = null;
    this.startMonitoring();
  }
  
  async checkHealth() {
    try {
      await this.client.ping();
      this.healthy = true;
      this.lastCheck = new Date();
      return true;
    } catch (error) {
      this.healthy = false;
      console.error('Health check failed:', error);
      return false;
    }
  }
  
  startMonitoring() {
    setInterval(() => {
      this.checkHealth();
    }, 30000); // Check every 30 seconds
  }
  
  getStatus() {
    return {
      healthy: this.healthy,
      lastCheck: this.lastCheck
    };
  }
}

const healthMonitor = new HealthMonitor(client);

// Expose health endpoint
app.get('/health', (req, res) => {
  const status = healthMonitor.getStatus();
  res.status(status.healthy ? 200 : 503).json(status);
});

Observability Best Practices

Structured Reasoning

Provide structured reasoning for better observability:
// Good: Structured reasoning
await client.callTool({
  name: "database_query",
  arguments: { 
    table: "users", 
    filters: { active: true },
    limit: 100 
  },
  metadata: {
    reasoning: "Fetching active users for dashboard display",
    context: {
      userRole: "admin",
      requestId: "req_abc123",
      feature: "user_management"
    },
    confidence: 0.95,
    alternatives: ["cache_lookup", "api_call"],
    expectedCost: 0.001,
    expectedDuration: 500
  }
});

// Bad: Minimal context
await client.callTool({
  name: "database_query",
  arguments: { table: "users" }
});

Cost Attribution

Track costs effectively:
// Track costs by feature/user/session
await client.callTool({
  name: "ai_analysis",
  arguments: { data: analysisData },
  metadata: {
    costAttribution: {
      userId: "user_123",
      sessionId: "session_456", 
      feature: "data_analysis",
      department: "engineering"
    },
    budgetTracking: {
      category: "ai_operations",
      maxCost: 0.50,
      alertThreshold: 0.40
    }
  }
});

Performance Tracking

Add performance markers:
// Track performance with markers
const startTime = performance.now();

await client.callTool({
  name: "complex_calculation",
  arguments: { dataset: largeDataset },
  metadata: {
    performance: {
      startTime: startTime,
      datasetSize: largeDataset.length,
      complexity: "high",
      cacheable: false
    },
    timing: {
      expectedDuration: 5000,
      timeoutWarning: 4000,
      maxAcceptableDuration: 10000
    }
  }
});

const endTime = performance.now();
console.log(`Tool call completed in ${endTime - startTime}ms`);

Development Workflow

Environment Management

  • Development
  • Testing
  • Production
// Development configuration
const client = new Client({
transport: new HTTPTransport({
baseUrl: process.env.AGENTFLARE_PROXY_URL,
headers: {
  "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
}
  apiKey: process.env.API_JWT_SECRET_DEV,
  projectId: process.env.AGENTFLARE_PROJECT_ID_DEV,
  environment: 'development',
  debug: true,
  logLevel: 'debug',
  sampling: { rate: 1.0 }, // 100% sampling in dev
  validateRequests: true,   // Validate all requests
  dryRun: false            // Actually make calls
});

Testing Strategy

// Unit tests
describe('Tool Calls', () => {
  beforeEach(() => {
    // Use test client with mocking
    client = new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    }
      apiKey: 'test-key',
      dryRun: true,
      mockResponses: {
        'search': { results: ['test result'] },
        'database_query': { rows: [{ id: 1, name: 'test' }] }
      }
    });
  });
  
  it('should handle search tool calls', async () => {
    const result = await client.callTool({
      name: 'search',
      arguments: { query: 'test' }
    });
    
    expect(result.results).toHaveLength(1);
    expect(result.results[0]).toBe('test result');
  });
});

// Integration tests
describe('Integration Tests', () => {
  it('should connect to real services in staging', async () => {
    const client = new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    }
      apiKey: process.env.API_JWT_SECRET_STAGING,
      environment: 'staging'
    });
    
    const health = await client.ping();
    expect(health.status).toBe('healthy');
  });
});

Monitoring and Alerting

Key Metrics to Monitor

Error Rate

Monitor tool call failure rates

Latency

Track response times and timeouts

Cost

Monitor API usage costs

Throughput

Track requests per second

Custom Alerting

// Set up custom alerting
const client = new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    }
  apiKey: process.env.API_JWT_SECRET,
  alerting: {
    enabled: true,
    webhookUrl: process.env.SLACK_WEBHOOK_URL,
    rules: [
      {
        metric: 'error_rate',
        threshold: 0.05,      // 5% error rate
        window: '5m',         // Over 5 minutes
        severity: 'critical'
      },
      {
        metric: 'avg_latency',
        threshold: 2000,      // 2 second avg latency
        window: '10m',
        severity: 'warning'
      },
      {
        metric: 'cost_per_hour',
        threshold: 10.00,     // $10/hour
        window: '1h',
        severity: 'warning'
      }
    ]
  }
});

Scaling Considerations

Load Balancing

// Multiple client instances for load balancing
const clients = [
  new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    } 
    apiKey: process.env.API_JWT_SECRET,
    region: 'us-east-1' 
  }),
  new Client({
  transport: new HTTPTransport({
    baseUrl: process.env.AGENTFLARE_PROXY_URL,
    headers: {
      "Authorization": `Bearer ${process.env.AGENTFLARE_API_KEY}`
    } 
    apiKey: process.env.API_JWT_SECRET,
    region: 'us-west-2' 
  })
];

function getClient() {
  // Simple round-robin load balancing
  return clients[Math.floor(Math.random() * clients.length)];
}

async function scaledToolCall(toolName, args) {
  const client = getClient();
  return client.callTool({ name: toolName, arguments: args });
}

Resource Management

// Resource management for high-volume applications
class ResourceManager {
  constructor() {
    this.activeConnections = 0;
    this.maxConnections = 100;
    this.queue = [];
  }
  
  async acquireConnection() {
    if (this.activeConnections < this.maxConnections) {
      this.activeConnections++;
      return true;
    }
    
    // Queue the request
    return new Promise((resolve) => {
      this.queue.push(resolve);
    });
  }
  
  releaseConnection() {
    this.activeConnections--;
    
    if (this.queue.length > 0) {
      const next = this.queue.shift();
      this.activeConnections++;
      next(true);
    }
  }
}

Next Steps


Following these best practices will help you build reliable, performant, and secure applications with Agentflare.
I