Detect: Middleware Detection
Add server-side AI agent detection to Next.js or Express applications
Goal
Add server-side AI agent detection to your Next.js or Express application using Checkpoint middleware. By the end of this cookbook, you'll have:
- Server-side detection running on every request
- Detection data flowing to your dashboard
- Access to detection results in your route handlers
- Foundation ready for enforcement (blocking) when you're ready
Best for: Applications that need server-side detection without blocking, or as a stepping stone to enforcement.
Prerequisites
- A Checkpoint account with a project created
- A Next.js 13+ or Express 4+ application
- Node.js 16+
Time Estimate
20 minutes
Steps
Install the Middleware Package
npm install @kya-os/agentshield-nextjsnpm install @kya-os/agentshield-expressGet Your API Key
- Log into your Checkpoint dashboard
- Select your project
- Go to Settings → API Keys
- Click Create API Key
- Copy the key (it starts with
as_)
Add it to your environment:
# .env.local
AGENTSHIELD_API_KEY=as_live_xxxxxxxxxxxx
CHECKPOINT_PROJECT_ID=proj_abc123def456Never commit API keys to source control. Use environment variables or a secrets manager.
Configure the Middleware
Create or update middleware.ts in your project root:
// middleware.ts
import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';
export default withAgentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
// No onBlock — detection only, no enforcement
});
export const config = {
matcher: [
// Match all paths except static assets
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
};This runs detection on every request but doesn't block anything.
Add the middleware to your Express app:
// app.ts or server.ts
import express from 'express';
import { createEnhancedAgentShieldMiddleware } from '@kya-os/agentshield-express';
const app = express();
// Add detection middleware
app.use(
createEnhancedAgentShieldMiddleware({
projectId: process.env.CHECKPOINT_PROJECT_ID!,
mode: 'detect', // Detection only, no blocking
onDetection: (event) => {
console.log(`Detected ${event.detectionClass} with ${event.confidence}% confidence`);
},
})
);
// Your routes
app.get('/', (req, res) => {
// Access detection data via req.agentShield
const detection = req.agentShield;
res.json({
message: 'Hello!',
visitor: {
class: detection?.detectionClass,
confidence: detection?.confidence,
},
});
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});Access Detection Data in Routes
Detection data is available in request headers:
// app/api/protected/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
// Detection class is added to headers by middleware
const detectionClass = request.headers.get('kya-class');
const confidence = request.headers.get('kya-confidence');
const agentName = request.headers.get('kya-agent-name');
return NextResponse.json({
message: 'API response',
detection: {
class: detectionClass,
confidence: confidence ? parseInt(confidence, 10) : null,
agentName: agentName || null,
},
});
}// pages/api/protected.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// Detection class is added to headers by middleware
const detectionClass = req.headers['kya-class'];
const confidence = req.headers['kya-confidence'];
res.json({
message: 'API response',
detection: {
class: detectionClass,
confidence: confidence ? parseInt(String(confidence), 10) : null,
},
});
}Detection is available on the request object:
// routes/api.ts
import express from 'express';
const router = express.Router();
router.get('/data', (req, res) => {
const detection = req.agentShield;
// Log AI agents for monitoring
if (detection?.detectionClass === 'ai_agent') {
console.log(`AI Agent ${detection.agentName} accessing /api/data`);
}
res.json({
data: 'your data here',
detection: {
class: detection?.detectionClass,
confidence: detection?.confidence,
agentName: detection?.agentName,
},
});
});
export default router;Add Logging and Monitoring
Create a detection handler to log activity:
// middleware.ts
import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';
export default withAgentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onDetection: async (detection, request) => {
// Log AI agents
if (detection.detectionClass === 'ai_agent') {
console.log(
JSON.stringify({
event: 'ai_agent_detected',
agent: detection.agentName,
confidence: detection.confidence,
path: request.nextUrl.pathname,
timestamp: new Date().toISOString(),
})
);
}
// Send to your analytics/monitoring
// await logToDatadog(detection);
// await sendToSlack(detection);
},
});
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};// middleware/detection-logger.ts
import { createEnhancedAgentShieldMiddleware } from '@kya-os/agentshield-express';
export const detectionMiddleware = createEnhancedAgentShieldMiddleware({
projectId: process.env.CHECKPOINT_PROJECT_ID!,
mode: 'detect',
onDetection: (event) => {
// Structured logging
console.log(
JSON.stringify({
event: 'agent_detection',
class: event.detectionClass,
confidence: event.confidence,
agentName: event.agentName,
path: event.request.path,
ip: event.request.ip,
userAgent: event.request.headers['user-agent'],
timestamp: new Date().toISOString(),
})
);
// Alert on high-confidence AI agents
if (event.detectionClass === 'ai_agent' && event.confidence > 80) {
// alertOps(`High-confidence AI agent: ${event.agentName}`);
}
},
});Test the Integration
Test as a normal user:
curl http://localhost:3000/api/protected
# Should return detection.class: "human"Test as an AI agent:
curl -H "User-Agent: Mozilla/5.0 (compatible; GPTBot/1.0; +https://openai.com/gptbot)" \
http://localhost:3000/api/protected
# Should return detection.class: "ai_agent"Test as a bot:
curl -H "User-Agent: Googlebot/2.1" \
http://localhost:3000/api/protected
# Should return detection.class: "bot"Verify It's Working
Dashboard Check
- Visit your Checkpoint dashboard
- Select your project
- Go to Analytics
- You should see detections from your test requests
Log Check
If you added logging, check your console:
{
"event": "agent_detection",
"class": "ai_agent",
"confidence": 85,
"agentName": "ChatGPT",
"path": "/api/protected",
"timestamp": "2024-01-15T10:30:00.000Z"
}Troubleshooting
Middleware Not Running
| Symptom | Cause | Fix |
|---|---|---|
| No detection headers | Middleware not loaded | Check middleware.ts is in project root |
| Detection always null | Matcher not matching | Review config.matcher patterns |
| "API key invalid" error | Wrong key | Copy key from dashboard again |
Detection Always "incomplete_data"
This means not enough signals for confident classification:
- Check headers — Ensure User-Agent is present
- Check IP — Some detection signals use IP geolocation
- Wait for more data — First requests may have limited signals
Performance Issues
If detection is adding latency:
- Use Redis storage for session caching
- Review the matcher to exclude unnecessary routes
- Check API key rate limits in your dashboard
What You Learned
- How to add server-side detection to Next.js and Express
- How to access detection data in your routes
- How to log and monitor detections
- How to test with different user agents
Next Steps
Ready to start blocking detected agents? See:
| Goal | Next Cookbook |
|---|---|
| Block AI agents | Middleware Enforcement |
| DNS-level blocking | Gateway Setup |
| Configure policies | Policy Configuration |