AgentShield
Server Integrations

Express Integration

Server-side AI agent detection for Express and Node.js applications

Overview

The AgentShield Express integration provides robust server-side AI agent detection for Node.js applications. With simple middleware integration, you can protect your APIs and web applications from automated access.

Features

Performance

  • < 2ms latency - Minimal request overhead
  • Non-blocking - Asynchronous processing
  • Caching support - Reduce API calls
  • Connection pooling - Efficient resource usage

Protection

  • Middleware-based - Easy integration
  • Route-level control - Protect specific endpoints
  • Session tracking - Monitor agents across requests
  • Custom handlers - Flexible response strategies

Developer Experience

  • TypeScript support - Full type definitions
  • Express 4+ compatible - Works with existing apps
  • Error boundaries - Graceful failure handling
  • Extensive logging - Debug and monitoring

Installation

npm install @kya-os/agentshield-express

Quick Setup

Basic Middleware

const express = require('express');
const { agentShield } = require('@kya-os/agentshield-express');

const app = express();

// Add AgentShield middleware
app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block', // 'block', 'log', 'redirect', 'custom'
    confidenceThreshold: 0.8,
  })
);

// Your routes
app.get('/', (req, res) => {
  res.send('Protected by AgentShield');
});

app.listen(3000);

TypeScript Setup

import express from 'express';
import { agentShield, AgentShieldConfig } from '@kya-os/agentshield-express';

const app = express();

const config: AgentShieldConfig = {
  apiKey: process.env.AGENTSHIELD_API_KEY!,
  onAgentDetected: 'block',
  confidenceThreshold: 0.8,
};

app.use(agentShield(config));

app.listen(3000);

Configuration Options

Basic Configuration

agentShield({
  // Required
  apiKey: string,                    // Your API key

  // Detection Settings
  onAgentDetected: 'block' | 'log' | 'redirect' | 'custom',
  confidenceThreshold: number,       // 0-1 (default: 0.8)

  // Response Customization
  blockMessage: string,              // Custom block message
  blockStatusCode: number,           // HTTP status (default: 403)
  redirectUrl: string,               // Redirect URL for agents

  // Custom Handler
  customHandler: (req, res, result) => void,

  // Session Tracking
  sessionTracking: {
    enabled: boolean,               // Track sessions (default: true)
    storage: 'memory' | 'redis',    // Session storage
    duration: number                // Session duration in ms
  },

  // Performance
  cacheResults: boolean,            // Cache detection results
  cacheDuration: number,            // Cache TTL in seconds

  // Advanced
  skipPaths: string[],              // Paths to skip
  skipMethods: string[],            // HTTP methods to skip
  allowedAgents: string[],          // Whitelisted user agents

  // Debug
  debug: boolean,                   // Enable debug logging
  logLevel: 'error' | 'warn' | 'info' | 'debug'
});

Environment Variables

# .env
AGENTSHIELD_API_KEY=your_api_key_here
AGENTSHIELD_ACTION=block
AGENTSHIELD_THRESHOLD=0.8
AGENTSHIELD_DEBUG=false
REDIS_URL=redis://localhost:6379  # If using Redis sessions

Usage Patterns

Global Protection

// Protect all routes
app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block',
  })
);

// All subsequent routes are protected
app.get('/api/data', (req, res) => {
  res.json({ protected: true });
});

Route-Specific Protection

const protectRoute = agentShield({
  apiKey: process.env.AGENTSHIELD_API_KEY,
  onAgentDetected: 'block',
});

// Only protect specific routes
app.get('/api/sensitive', protectRoute, (req, res) => {
  res.json({ sensitive: 'data' });
});

// Unprotected route
app.get('/api/public', (req, res) => {
  res.json({ public: 'data' });
});

Conditional Protection

app.use((req, res, next) => {
  // Skip protection for authenticated users
  if (req.user && req.user.authenticated) {
    return next();
  }

  // Apply AgentShield for unauthenticated requests
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block',
  })(req, res, next);
});

Custom Response Handlers

Custom Block Response

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'custom',
    customHandler: (req, res, result) => {
      // Log detection
      console.log('Agent detected:', {
        ip: req.ip,
        userAgent: req.headers['user-agent'],
        confidence: result.confidence,
      });

      // Custom response
      res.status(403).json({
        error: 'Access Denied',
        reason: 'Automated access detected',
        confidence: result.confidence,
      });
    },
  })
);

Graduated Response

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'custom',
    customHandler: (req, res, result) => {
      if (result.confidence > 0.95) {
        // High confidence: block
        res.status(403).send('Forbidden');
      } else if (result.confidence > 0.8) {
        // Medium confidence: challenge
        res.redirect('/challenge?return=' + req.originalUrl);
      } else if (result.confidence > 0.6) {
        // Low confidence: rate limit
        res.setHeader('X-RateLimit-Limit', '10');
        res.setHeader('X-RateLimit-Remaining', '5');
        next();
      } else {
        // Very low: allow
        next();
      }
    },
  })
);

Logging and Analytics

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'log',
    customHandler: async (req, res, result) => {
      // Send to analytics
      await analytics.track({
        event: 'agent_detected',
        properties: {
          path: req.path,
          method: req.method,
          confidence: result.confidence,
          signals: result.signals,
        },
      });

      // Continue processing
      next();
    },
  })
);

Session Tracking

Memory Sessions

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    sessionTracking: {
      enabled: true,
      storage: 'memory',
      duration: 3600000, // 1 hour
    },
  })
);

Redis Sessions

const redis = require('redis');
const client = redis.createClient({
  url: process.env.REDIS_URL,
});

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    sessionTracking: {
      enabled: true,
      storage: 'redis',
      redisClient: client,
      duration: 86400000, // 24 hours
    },
  })
);

Custom Session Storage

class CustomSessionStore {
  async get(sessionId) {
    // Retrieve session
  }

  async set(sessionId, data, ttl) {
    // Store session
  }

  async delete(sessionId) {
    // Delete session
  }
}

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    sessionTracking: {
      enabled: true,
      store: new CustomSessionStore(),
    },
  })
);

API Protection Strategies

REST API Protection

// Protect API routes
app.use(
  '/api',
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block',
    blockStatusCode: 403,
    blockMessage: JSON.stringify({
      error: 'Forbidden',
      message: 'API access requires authentication',
    }),
  })
);

app.get('/api/users', (req, res) => {
  res.json({ users: [] });
});

GraphQL Protection

const { graphqlHTTP } = require('express-graphql');

// Protect GraphQL endpoint
app.use(
  '/graphql',
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block',
  }),
  graphqlHTTP({
    schema: schema,
    graphiql: true,
  })
);

WebSocket Protection

const server = require('http').createServer(app);
const io = require('socket.io')(server);

// Protect WebSocket connections
io.use(async (socket, next) => {
  const result = await detectAgent(socket.handshake);

  if (result.isAgent && result.confidence > 0.8) {
    next(new Error('Connection rejected'));
  } else {
    next();
  }
});

Rate Limiting Integration

const rateLimit = require('express-rate-limit');

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'custom',
    customHandler: (req, res, result) => {
      if (result.isAgent) {
        // Apply stricter rate limits for detected agents
        const strictLimiter = rateLimit({
          windowMs: 15 * 60 * 1000, // 15 minutes
          max: 10, // 10 requests per window
        });
        strictLimiter(req, res, next);
      } else {
        next();
      }
    },
  })
);

Error Handling

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onAgentDetected: 'block',
    onError: (error, req, res, next) => {
      console.error('AgentShield error:', error);

      // Continue without protection on error
      next();
    },
  })
);

// Global error handler
app.use((err, req, res, next) => {
  if (err.name === 'AgentShieldError') {
    // Handle AgentShield specific errors
    res.status(500).json({
      error: 'Detection service unavailable',
    });
  } else {
    next(err);
  }
});

Testing

Unit Testing

const request = require('supertest');
const app = require('./app');

describe('AgentShield Protection', () => {
  it('should block bot user agents', async () => {
    const response = await request(app)
      .get('/api/protected')
      .set('User-Agent', 'bot/1.0')
      .expect(403);

    expect(response.text).toContain('Forbidden');
  });

  it('should allow normal browsers', async () => {
    const response = await request(app)
      .get('/api/protected')
      .set('User-Agent', 'Mozilla/5.0...')
      .expect(200);

    expect(response.body).toHaveProperty('data');
  });
});

Integration Testing

// Test with mock API
const nock = require('nock');

beforeEach(() => {
  nock('https://kya.vouched.id').post('/v1/detect').reply(200, {
    isAgent: true,
    confidence: 0.95,
  });
});

Performance Optimization

Use caching and connection pooling to minimize latency and API calls.

Caching Results

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    cacheResults: true,
    cacheDuration: 300, // 5 minutes
    cacheKeyGenerator: (req) => {
      // Custom cache key
      return `${req.ip}:${req.headers['user-agent']}`;
    },
  })
);

Connection Pooling

const http = require('http');
const https = require('https');

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    httpAgent: new http.Agent({
      keepAlive: true,
      maxSockets: 10,
    }),
    httpsAgent: new https.Agent({
      keepAlive: true,
      maxSockets: 10,
    }),
  })
);

Monitoring

const prometheus = require('prom-client');

const detectionCounter = new prometheus.Counter({
  name: 'agentshield_detections_total',
  help: 'Total agent detections',
  labelNames: ['action', 'confidence_range'],
});

app.use(
  agentShield({
    apiKey: process.env.AGENTSHIELD_API_KEY,
    onDetection: (result) => {
      const range = result.confidence > 0.8 ? 'high' : 'low';
      detectionCounter.inc({
        action: result.isAgent ? 'blocked' : 'allowed',
        confidence_range: range,
      });
    },
  })
);

Best Practices

  1. Use environment variables for API keys
  2. Enable caching in production
  3. Implement error handling for service failures
  4. Monitor detection patterns in your analytics
  5. Test with various user agents before deployment
  6. Use graduated responses based on confidence
  7. Implement rate limiting for detected agents

Next Steps

Command Palette

Search for a command to run...