Arcjet Launches on Product Hunt: A Practical Guide to Securing AI Agents in Production
Introduction
Arcjet — real‑time security for AI agents — just landed on Product Hunt, and developers are already buzzing. With jailbreaks, data‑exfiltration, and model‑stealing attacks on the rise, you can’t afford to treat LLM protection as an afterthought. This article shows you exactly how to lock down your AI services today: we’ll walk through the biggest threats, dissect Arcjet’s middleware design, and give you copy‑and‑paste code for Node.js, Python, and Cloud Functions. By the end you’ll have a working demo that talks to OpenAI, Anthropic, and a locally hosted LLaMA‑2 model, plus a Python script that generates risk reports and pushes alerts to Slack. We’ll also compare Arcjet with OpenAI Guardrails and LangChain policies, hand you a deployment checklist, and answer the most‑asked questions from the community.
1. Core Threats for AI Agents
| Threat | Typical Impact | Why Real‑Time Protection Helps |
|---|---|---|
| Prompt injection / jailbreak | Leaked credentials, unintended actions | Intercepts malicious prompts before they reach the model |
| Model stealing | Loss of IP, competitive disadvantage | Rate‑limits and query‑pattern detection stop bulk extraction |
| Data exfiltration | PII leakage, regulatory fines (HIPAA, GDPR) | Masking/Pseudonymisation and audit logs enforce compliance |
| Prompt‑level bias | Harmful outputs, brand damage | Rule‑engine can reject or rewrite biased prompts instantly |
2. Arcjet Architecture at a Glance
Client → Arcjet Middleware → LLM Provider (OpenAI / Anthropic / Azure / Self‑hosted) → Response → Client
- Language‑agnostic – works with any HTTP‑based LLM endpoint.
- Pre‑request rule engine – validates, rate‑limits, and sanitises the prompt before it is sent.
- Post‑response hooks – optional logging, redaction, and alerting.
- Deploy anywhere – Cloudflare Workers, AWS Lambda, GCP Cloud Functions, or a Docker container on‑prem.
3. Getting Started – Code Samples
3.1 Node.js (Express)
// server.js
import express from 'express';
import arcjet from '@arcjet/middleware';
import fetch from 'node-fetch';
const app = express();
app.use(express.json());
// Initialise Arcjet middleware
const aj = arcjet({
apiKey: process.env.ARCJET_API_KEY,
rules: [
{ type: 'promptLength', maxTokens: 800 },
{ type: 'rateLimit', maxRequests: 100, per: 'minute' },
{ type: 'piiMask', fields: ['userEmail', 'phone'] },
],
});
app.post('/chat', aj.protect, async (req, res) => {
const { model, prompt } = req.body;
const llmResponse = await fetch(`https://api.openai.com/v1/${model}`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ prompt, max_tokens: 512 }),
});
const data = await llmResponse.json();
res.json(data);
});
app.listen(3000, () => console.log('🚀 server listening on :3000'));
Run: node server.js
3.2 Python (FastAPI)
# main.py
import os
from fastapi import FastAPI, Request, HTTPException
from arcjet import ArcjetMiddleware
app = FastAPI()
aj = ArcjetMiddleware(
api_key=os.getenv("ARCJET_API_KEY"),
rules=[
{"type": "promptLength", "max_tokens": 800},
{"type": "rateLimit", "max_requests": 150, "per": "minute"},
{"type": "piiMask", "fields": ["email", "ssn"]},
],
)
@app.post("/chat")
async def chat(request: Request):
await aj.protect(request) # ← blocks malicious payloads
payload = await request.json()
# Forward to Anthropic
async with httpx.AsyncClient() as client:
resp = await client.post(
"https://api.anthropic.com/v1/complete",
headers={"x-api-key": os.getenv("ANTHROPIC_API_KEY")},
json={"prompt": payload["prompt"], "max_tokens_to_sample": 512},
)
return resp.json()
Run: uvicorn main:app --reload
3.3 Google Cloud Function (Node)
// index.js
const arcjet = require('@arcjet/middleware');
const fetch = require('node-fetch');
const aj = arcjet({
apiKey: process.env.ARCJET_API_KEY,
rules: [{ type: 'rateLimit', maxRequests: 200, per: 'minute' }],
});
exports.secureChat = async (req, res) => {
try {
await aj.protect(req); // throws if blocked
const { prompt } = req.body;
const llm = await fetch('https://api.openai.com/v1/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: 'gpt-4o', prompt, max_tokens: 512 }),
});
const data = await llm.json();
res.status(200).send(data);
} catch (e) {
if (e.code === 'ARCJET_BLOCKED') {
res.status(403).json({ error: 'Request blocked by security policy' });
} else {
res.status(500).json({ error: e.message });
}
}
};
Deploy with:
gcloud functions deploy secureChat \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--set-env-vars ARCJET_API_KEY=...,OPENAI_API_KEY=...
4. Generating Risk Reports & Slack Alerts (Python)
# risk_report.py
import os, json, requests
from datetime import datetime
from arcjet import ArcjetClient
client = ArcjetClient(api_key=os.getenv("ARCJET_API_KEY"))
def fetch_logs():
# Pull last 24 h of audit logs
resp = client.get("/audit?since=24h")
return resp.json()
def summarize(logs):
risks = {"jailbreak":0, "pii":0, "rate_limit":0}
for entry in logs:
if entry["rule"] == "jailbreak": risks["jailbreak"] += 1
if entry["rule"] == "piiMask": risks["pii"] += 1
if entry["rule"] == "rateLimit": risks["rate_limit"] += 1
return risks
def send_to_slack(risks):
webhook = os.getenv("SLACK_WEBHOOK")
msg = {
"text": f"*Arcjet Risk Summary* ({datetime.utcnow().isoformat()} UTC)\n"
f"• Jailbreak attempts: {risks['jailbreak']}\n"
f"• PII exposures blocked: {risks['pii']}\n"
f"• Rate‑limit violations: {risks['rate_limit']}"
}
requests.post(webhook, json=msg)
if __name__ == "__main__":
logs = fetch_logs()
risks = summarize(logs)
send_to_slack(risks)
Schedule with Cloud Scheduler or a cron job to get daily visibility.
5. Arcjet vs. Competing Solutions
| Feature | Arcjet | OpenAI Guardrails | LangChain Policies |
|---|---|---|---|
| Scope | Any LLM endpoint (cloud or self‑hosted) | OpenAI APIs only | LangChain‑specific, works when you use LangChain wrappers |
| Placement | Middleware before the model | Prompt‑level checks (inside the request) | In‑code policy objects |
| Rate limiting | Built‑in, configurable per‑app | No native support | Must be coded manually |
| PII masking & retention | Automatic, audit‑ready | Manual prompt engineering | Not provided out‑of‑the‑box |
| Observability | Centralised audit log, searchable UI | Limited to OpenAI usage logs | Depends on your logging implementation |
| Latency impact | ~23 ms (512‑token request on t3.medium) | Negligible (in‑prompt) | Varies with implementation |
6. Deployment Checklist
| ✅ | Item |
|---|---|
| 1 | Create an Arcjet account and store the API key in a secret manager. |
| 2 | Define rule set (prompt length, rate limit, PII fields, jailbreak patterns). |
Herramienta mencionada: Groq Cloud
Top comments (0)