- name
- arcjet
- license
- Apache-2.0
- description
- Add Arcjet security protection to HTTP routes, AI agent tool calls, MCP servers, background jobs, and queue workers. Covers rate limiting, bot detection, email validation, prompt injection, sensitive information blocking (including Rampart NER), content moderation, capture/flush, remote Guard policies, typed inputs, and abuse prevention. Works in JavaScript/TypeScript, Python, and Go. HTTP frameworks share this skill. JS Guard adapters (Vercel AI SDK, Eve, Mastra, LangChain, LangGraph, OpenAI Agents, Genkit, Google ADK, Strands, TanStack AI, Claude Agent SDK, Claude Managed Agents) are per-adapter reference files loaded from Step 3 — do not keep the whole JS Guard reference in context. Official Python LangChain, CrewAI, OpenAI Agents, Claude Agent SDK, Claude Managed Agents, and Strands Agents have dedicated integrate-arcjet-guard skills. Microsoft Agent Framework for Go has a dedicated integrate-arcjet-guard-agent-framework-go skill. Use when the user wants security, rate limiting, bot protection, or abuse prevention – "protect my API," "rate limit tool calls," "block bots," "secure my endpoint," or "prevent abuse" – even without naming Arcjet.
- metadata
- {"author":"arcjet"}
# Arcjet
## Contents
- [Add Arcjet protection to your app](#add-arcjet-protection-to-your-app)
- [Choose protections](#choose-protections)
- [Resources](#resources)
Python Guard adapters for LangChain, CrewAI, OpenAI Agents, Claude Agent SDK, Claude Managed Agents, and Strands Agents are dedicated skills (see Step 3). JS Guard adapters are per-file references under `references/guards_js_*.md`. Shared fundamentals stay in [references/guards_javascript.md](references/guards_javascript.md) and [references/guards_python.md](references/guards_python.md).
## Add Arcjet protection to your app
### Checklist
- [ ] **Step 1:** Verify language support (JS/TS, Python, or Go only – stop if unsupported)
- [ ] **Step 2:** Connect to Arcjet platform (CLI → MCP → manual Console setup)
- [ ] **Step 3:** Detect protection type and read the appropriate reference file
- [ ] **Step 4:** Implement protection (separate client file, correct SDK, correct patterns)
- [ ] **Step 5:** Verify decisions are firing correctly (trigger a real call, then check CLI / MCP / Console)
### Step 1: Check language support
If the project's server-side code is not JavaScript, TypeScript, Python, or Go → tell the user in chat that Arcjet doesn't support their language yet. Don't modify the project, don't write a `NOTES.md`, don't invent a package. Just say it and stop.
### Step 2: Get an `ARCJET_KEY` into the project's env file
Before writing any code, the project needs a real `ARCJET_KEY` in its env file. Don't write Arcjet code first and "leave the key as a TODO" – that just produces dead code. Get the key first, then wire it up.
**In order of preference:**
1. **Arcjet CLI** (preferred). Check whether you're already signed in, then retrieve a key.
2. **Arcjet MCP server** (endpoint: `https://api.arcjet.com/mcp`) – for clients with built-in MCP. See [references/mcp.md](references/mcp.md).
3. **Manual** (last resort): tell the user to grab a key from https://console.arcjet.com.
#### CLI bootstrap (the normal path)
```bash
npx -y @arcjet/cli@latest auth status # is the user already signed in?
# if not signed in:
npx -y @arcjet/cli@latest auth login # browser device flow, see references/cli.md
npx -y @arcjet/cli@latest teams list --output json --fields id,name
npx -y @arcjet/cli@latest sites list --team-id <team_id> --output json --fields id,name
# if no suitable site exists:
npx -y @arcjet/cli@latest sites create --team-id <team_id> --name "<project>"
npx -y @arcjet/cli@latest sites get-key --site-id <site_id> --output json --fields key
```
Write the `key` value to the project's env file as `ARCJET_KEY=ajkey_...`. Match whatever the project already does – filename, `.env.example` companion, `.gitignore` entry. If the project doesn't have a convention yet, default to whatever the framework expects and add the env file to `.gitignore`. Never hardcode the key in source.
See [references/cli.md](references/cli.md) for install options beyond `npx`, agent-mode flags, and the full command reference.
#### Install the SDK with the project's package manager
Once you know which SDK you need (see Step 3), install it with the package manager the project already uses: `npm install`, `pnpm add`, `yarn add`, `bun add`, `pip install`, `uv add`, `poetry add`, or `go get`. Don't hand-edit `package.json` / `requirements.txt` / `go.mod` and guess a version: typed versions go stale (`@arcjet/next` is currently `1.13.0`; Python `arcjet` is `1.2.0`; Go must use a module tag, not a copied pseudo-version), and the lockfile/module metadata won't get updated. Let the package manager pick the real version and pin it.
### Step 3: Detect protection type and read the reference
Determine which protection type applies:
| | **Request-based** | **Guard** |
| --------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **When to use** | Code has an HTTP request object (Express `req`, Next.js `Request`, FastAPI `Request`) | No HTTP request (tool calls, MCP handlers, queue workers, background jobs, agent loops) |
| **JS/TS SDK** | Framework adapters such as `@arcjet/next`, `@arcjet/node`, `@arcjet/fastify` | `@arcjet/guard` |
| **Python SDK** | `arcjet` (with `arcjet()` / `arcjet_sync()`) | `arcjet` (with `launch_arcjet()` / `launch_arcjet_sync()`) |
| **Go SDK** | `github.com/arcjet/arcjet-go` (with `NewClient`) | `github.com/arcjet/arcjet-go` (with `NewGuardClient`) |
| **Entry point** | `protect(request)` / `Protect(ctx, r)` | Core JS `guard({ label, rules })`; Python `guard(label, …)`; Go `Guard(ctx, request)`. Wrappers take `action`, not `label`. |
A single project can use both – for example, request-based on API routes and Guard on agent tool calls. If the project already uses a supported agent framework, prefer the official wrapper over hand-wrapping every tool. In Python, load the dedicated skill (table below) — not a raw `guard()` around every callable, and not the JS `@arcjet/guard/...` path. In JavaScript, load fundamentals plus **exactly one** adapter file from the JS table — not the sibling adapters. In Go, load the Microsoft Agent Framework skill when that framework is present; otherwise use `GuardAction` from the Go Guard reference.
**Coding-agent hooks (Claude Code / GitHub Copilot) are a third path.** There is no SDK and no `guard()` call. Publishing a policy attached to **Execute on** (Tool call or Prompt) turns it on. Install the HTTP hooks from https://docs.arcjet.com/coding-agents — copy the templates, do not invent URLs. Hook URLs must not name a policy and must omit `?surface=` (managed settings reach CLI, IDE, Desktop, and cloud; a hard-coded `cli` mislabels most traffic). Author the policy via MCP ([references/mcp.md](references/mcp.md)).
**Common misclassifications to watch for:**
- **MCP servers**: the word "server" is misleading. MCP tools don't receive HTTP requests – they're invoked by an MCP client over stdio or SSE. Use **Guard**, not request-based.
- **Background jobs / queue consumers**: no HTTP request at the protection site. Use **Guard**.
- **Server actions / RPC over HTTP** (Next.js server actions, tRPC): there _is_ an HTTP request underneath. Use **request-based**.
- **Agent tool calls inside a request handler**: if you want to limit per-user-per-route, request-based is fine. If you want per-tool budgets independent of any HTTP boundary, use Guard at the tool call site.
Read the appropriate reference:
- **Request-based JS/TS**: [references/requests_javascript.md](references/requests_javascript.md)
- **Request-based Python**: [references/requests_python.md](references/requests_python.md)
- **Request-based Go**: [references/requests_go.md](references/requests_go.md)
- **Guard JS/TS fundamentals**: [references/guards_javascript.md](references/guards_javascript.md) — then exactly one adapter file from the table in that file (source of truth; do not copy it here)
- **Guard Python**: [references/guards_python.md](references/guards_python.md)
- **Guard Go**: [references/guards_go.md](references/guards_go.md)
When the project already uses an official JS agent framework, open the fundamentals file and load **exactly one** adapter from its table. Do not open sibling adapters.
When the project already uses an official Python agent framework, load the dedicated skill instead of the long adapter sections that used to live in the Python Guard reference:
| Python framework | Import | Skill |
| --------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| LangChain (`BaseTool` / `create_agent`) | `arcjet.guard.langchain` | [integrate-arcjet-guard-langchain-py](../integrate-arcjet-guard-langchain-py/SKILL.md) |
| CrewAI | `arcjet.guard.crewai` | [integrate-arcjet-guard-crewai](../integrate-arcjet-guard-crewai/SKILL.md) |
| OpenAI Agents | `arcjet.guard.openai_agents` | [integrate-arcjet-guard-openai-agents-py](../integrate-arcjet-guard-openai-agents-py/SKILL.md) |
| Claude Agent SDK | `arcjet.guard.claude_agent_sdk` | [integrate-arcjet-guard-claude-agent-sdk-py](../integrate-arcjet-guard-claude-agent-sdk-py/SKILL.md) |
| Claude Managed Agents | `arcjet.guard.claude_managed_agents` | [integrate-arcjet-guard-claude-managed-agents-py](../integrate-arcjet-guard-claude-managed-agents-py/SKILL.md) |
| Strands Agents | `arcjet.guard.strands_agents` | [integrate-arcjet-guard-strands-agents-py](../integrate-arcjet-guard-strands-agents-py/SKILL.md) |
When the project is Go and already uses Microsoft Agent Framework for Go, load the dedicated skill:
| Go framework | Surfaces | Import | Skill |
| ------------------------- | ------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Microsoft Agent Framework | `functool`, `mcptool`, `agent.Config.Middlewares` | `github.com/arcjet/arcjet-go/agentframework` | [integrate-arcjet-guard-agent-framework-go](../integrate-arcjet-guard-agent-framework-go/SKILL.md) |
These references explain architectural decisions and patterns that can't be inferred from the source code alone. For exact API signatures, read the installed package's types and doc comments.
### Step 4: Implement protection
Follow the patterns in the reference file from Step 3. Key principles:
#### Request-based (HTTP routes):
- Create shared clients outside handlers and include Shield as a base rule. Use the exact constructor and rule names from the language reference. JS HTTP rules omitted `mode` default to `DRY_RUN` – pass `mode: "LIVE"` to enforce. Python HTTP factories require `mode=` (`TypeError` if omitted). Go HTTP Protect rules also default to dry run – set `Mode: arcjet.ModeLive` to enforce.
- In JavaScript/TypeScript, create one `arcjet()` client and use `withRule()` for route-specific extras so clones share the decision cache. Check `decision.isDenied()`. Sibling `arcjet()` constructors do not share cache. `detectBot` requires exactly one of `allow` or `deny` (neither or both throws).
- In Python, create one `arcjet()` / `arcjet_sync()` client and use `with_rule()` for route-specific extras so clones share `DecisionCache`. Check `decision.is_denied()`. Sibling constructors do not share cache.
- In Go, create one `NewClient` at package scope. `WithRule()` derives route-specific clients that share the parent cache, and returns `(*Client, error)`, so handle initialization errors. Check `decision.IsDenied()`. Separate `NewClient` calls do not share cache.
Ver en GitHub