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
- Use environment variables for API keys
- Enable caching in production
- Implement error handling for service failures
- Monitor detection patterns in your analytics
- Test with various user agents before deployment
- Use graduated responses based on confidence
- Implement rate limiting for detected agents
Next Steps
- Next.js Integration - Edge-optimized middleware for Next.js
- GTM Integration - Next.js + Google Tag Manager guide
- Package Selection - Compare all integration options