Skip to content

Agent get started

Arcjet is the AI agent runtime security platform. Discover the agents running in your organization, enforce policy across every action, prompt, and tool call, and keep the evidence to prove what happened. Detect prompt injection, authorize agent tool calls, redact PII, and block bots and abuse.

Agents can register on behalf of the user using agent registration.

Read this section first and skip to the path that matches the project. Most projects need one.

What you’re protectingPath
A developer’s coding agent (Claude Code, GitHub Copilot, OpenAI Codex, Cursor)Secure the coding agent. No package to install.
An agent you built (tool calls, MCP servers, queue workers)Guard with @arcjet/guard or arcjet.guard.
HTTP routes and API endpointsProtect with a request SDK.

Detect which one applies by reading the project manifest:

  • package.json with next, express, fastify, @nestjs/core, @sveltejs/kit, hono, @remix-run/node, react-router, astro, or nuxt, or a Bun or Deno runtime, means a web application.
  • pyproject.toml or requirements.txt with fastapi or flask means a web application.
  • go.mod means the Go SDK with net/http or any router that exposes *http.Request.
  • An agent framework in either manifest (ai, eve, genkit, langchain, @langchain/langgraph, @mastra/core, @openai/agents, @google/adk, google-adk, @cloudflare/think, @strands-agents/sdk, @tanstack/ai, or crewai) means the project builds its own agent. Use the guard adapter for that framework, instead of or alongside a request SDK.

Two package names look alike and are different products. @anthropic-ai/sdk or anthropic calling hosted sessions and events.send is Claude Managed Agents. @anthropic-ai/claude-agent-sdk or claude-agent-sdk with a local query() loop is the Claude Agent SDK.

Protect (request SDKs)Guard (@arcjet/guard, arcjet.guard, NewGuardClient)
Designed forHTTP route handlers, API endpointsAI tool calls, MCP servers, queue workers, background jobs
Request objectRequiredNot needed
Rate limit keyIP or characteristicsExplicit key string at call time
Rate limiting / prompt injection / sensitive info✅✅
Bot protection / Shield / email validation / filters / IP analysis✅–
Content moderation–✅
Custom rules–✅

A single application can use both: request-based protection on API routes, and guards inside tool handlers, queue workers, and MCP tools.

Skills are the primary entry point for setting up Arcjet in an agentic workflow. They give your agent the documentation to detect the framework, install the SDK, and wire up protection rules.

Terminal window
npx skills add arcjet/skills

Then describe what you want to protect. The skill handles the rest. For the source, see github.com/arcjet/skills.

Skills handle the SDK and rule integration in your code. To create sites, retrieve ARCJET_KEY, inspect requests, and manage remote configuration, the agent needs to talk to the Arcjet API. There are two transports:

  • Arcjet CLI for agents and humans working in a terminal (Claude Code, Codex, plugin tasks, CI). No editor or MCP setup required.
  • MCP server for online clients without shell access (ChatGPT, Claude Desktop) and clients with built-in MCP support (Claude Code, Codex CLI, Cursor, VS Code with Copilot, Windsurf).

The two transports overlap but aren’t identical. Both cover teams, sites, remote rules, traffic analysis, and request inspection. Agent guard policies are MCP-only, so an agent that has to author or publish a policy needs the MCP server. For the full surface, see the CLI command reference and the MCP tool list.

If the user doesn’t have an Arcjet account, direct them to console.arcjet.com to create one or register on their behalf using agent registration. Both transports authenticate as that user, so don’t prompt them for a token or an API key.

The Arcjet CLI manages sites, keys, and rules from the terminal:

Terminal window
npx -y @arcjet/cli@latest auth login
npx -y @arcjet/cli@latest teams list
npx -y @arcjet/cli@latest sites list --team-id team_01abc123
npx -y @arcjet/cli@latest sites get-key --site-id site_01abc123

auth login uses a browser-based device flow. For frequent use, install the binary so you can run arcjet <command> directly. See CLI install paths.

The Arcjet MCP server manages your account from an AI coding tool. For the per-client configuration steps, see MCP server setup.

Authentication uses OAuth on first connection. Claude Code and ChatGPT open a browser automatically. Cursor, Codex CLI, and VS Code prompt you to authenticate first, so the user may have to click through before any tool call succeeds.

Once connected, retrieve the site key:

  1. Call list-teams to get available teams.
  2. Call list-sites with the team ID to find the site, or call create-site to create one.
  3. Call get-site-key with the site ID to retrieve the ARCJET_KEY.

Whichever transport you used, set the key in the project environment:

# .env.local (Next.js, Astro) or .env (other frameworks)
ARCJET_KEY=ajkey_yourkey
ARCJET_ENV=development

ARCJET_ENV=development switches the SDK in the local app into development mode, which allows the private and loopback IP addresses that are normal on a developer machine. It’s read by the JavaScript and Python SDKs and ignored by the Go SDK, which has no development mode. It has nothing to do with the CLI or the MCP connection. For more information, see Environment variables.

Install the package for the framework you detected. Coding agents need no package at all.

Enforce security policies on developer coding agents. There is no package to install, and no code changes. An administrator configures the hooks the agent already fires. See Claude Code, GitHub Copilot, OpenAI Codex, and Cursor.

Protect custom-built agents with direct framework integrations. Each one uses the guard SDK (@arcjet/guard or arcjet.guard) with the framework package as a peer.

FrameworkInstall command
Claude Agent SDKnpm i @arcjet/guard @anthropic-ai/claude-agent-sdk or pip install "arcjet[claude-agent-sdk]"
Claude Managed Agentsnpm i @arcjet/guard @anthropic-ai/sdk or pip install "arcjet[claude-managed-agents]"
CrewAIpip install "arcjet>=1.0.0" "crewai>=1.15.3,<2"
Genkitnpm i @arcjet/guard genkit
Google ADKnpm i @arcjet/guard @google/adk or pip install "arcjet[google-adk]"
Cloudflare Thinknpm i @arcjet/guard @cloudflare/think
LangChainnpm i @arcjet/guard langchain @langchain/core or pip install "arcjet[langchain]"
LangGraphnpm i @arcjet/guard @langchain/langgraph @langchain/core
Mastranpm i @arcjet/guard @mastra/core
OpenAI Agentsnpm i @arcjet/guard @openai/agents or pip install "arcjet[openai-agents]"
Strands Agentsnpm i @arcjet/guard @strands-agents/sdk or pip install "arcjet[strands-agents]"
TanStack AInpm i @arcjet/guard @tanstack/ai
Vercel AI SDKnpm i @arcjet/guard ai @ai-sdk/provider-utils
Vercel Evenpm i @arcjet/guard eve

Where a row lists only an npm command, that adapter is JavaScript-only. Cloudflare Think is JavaScript-only. CrewAI is Python-only, and has no arcjet[crewai] extra, so install CrewAI yourself. LangChain splits its extras: arcjet[langchain] covers guard_tool and the capture handlers, and arcjet[langchain-agents] covers ArcjetMiddleware and ToolPolicy. Claude Managed Agents needs the extra steps in Claude Managed Agents. For every adapter, see Guards.

Import paths are versioned. @arcjet/guard/vercel-ai/v7 resolves and @arcjet/guard/vercel-ai does not, which is deliberate: an unversioned import throws ERR_PACKAGE_PATH_NOT_EXPORTED rather than silently changing behavior across a major version.

Create custom integrations and protect your application code.

FrameworkInstall command
Astronpx astro add @arcjet/astro
Bunbun add @arcjet/bun @arcjet/inspect
Bun + Honobun add @arcjet/bun @arcjet/inspect
Denodeno add npm:@arcjet/deno npm:@arcjet/inspect
Fastifynpm i @arcjet/fastify
Gogo get github.com/arcjet/arcjet-go@latest
NestJSnpm i @arcjet/nest
Next.jsnpm i @arcjet/next
Node.jsnpm i @arcjet/node @arcjet/inspect
Node.js + Expressnpm i @arcjet/node @arcjet/inspect
Node.js + Hononpm i @arcjet/node @arcjet/inspect
Nuxtnpx nuxt module add @arcjet/nuxt
Python + FastAPIpip install arcjet or uv add arcjet
Python + Flaskpip install arcjet or uv add arcjet
React Routernpm i @arcjet/react-router @arcjet/inspect
Remixnpm i @arcjet/remix @arcjet/inspect
SvelteKitnpm i @arcjet/sveltekit @arcjet/inspect

Claude Managed Agents is Anthropic’s hosted harness. It is not the Claude Agent SDK, so don’t install claude-agent-sdk or @anthropic-ai/claude-agent-sdk for this adapter.

For JavaScript, install the guard SDK with @anthropic-ai/sdk (>=0.86.0 <1):

Terminal window
npm i @arcjet/guard @anthropic-ai/sdk

For Python, install the extra, which brings anthropic>=0.92.0,<2:

Terminal window
pip install "arcjet[claude-managed-agents]"

Or uv add the same spec. One adapter, both languages. Import @arcjet/guard/claude-managed-agents/v0 (guardEvents, guardCustomTool, claudeManagedAgentsContext) or arcjet.guard.claude_managed_agents (guard_events, guard_custom_tool, claude_managed_agents_context).

This adapter has no protect() call. Screen inbound user.message with guardEvents or guard_events before events.send, and wrap custom tools with guardCustomTool or guard_custom_tool before your app executes them. On a custom-tool DENY, return user.custom_tool_result with is_error set.

Anthropic runs built-in tools and the default is always_allow, so there’s no pre-execution hook for bash or file tools. always_ask with user.tool_confirmation is opt-in human confirmation, not policy. For MCP, put Guard on servers you host. For more information, see Claude Managed Agents agent guard.

A typical setup has three steps:

  1. Create an Arcjet client once, outside request handlers.
  2. Configure rules.
  3. Call protect() or guard() at the protection site, then act on the decision.

Configure shield (WAF), detectBot, rate limiting (tokenBucket, fixedWindow, or slidingWindow), and optionally sensitiveInfo or detectPromptInjection for AI apps. Call protect() inside each route handler and check whether the decision was denied.

In Go, log the err from Protect and deny only when IsDenied() is true. A transport failure returns an ERROR decision that IsAllowed() treats as allowed, so use IsErrored() to distinguish it from a real allow. If the client or request is nil, Protect returns the zero Decision.

A guard call needs no request object. Create the client once, configure rules, then evaluate them at the action boundary:

import {
launchArcjet,
detectPromptInjection,
tokenBucket,
} from "@arcjet/guard";
// Create the client once, at module scope.
const arcjet = launchArcjet({ key: process.env.ARCJET_KEY! });
const promptScan = detectPromptInjection();
const lookupLimit = tokenBucket({
refillRate: 10,
intervalSeconds: 60,
maxTokens: 10,
});
export async function lookupOrder(userId: string, orderNumber: string) {
const decision = await arcjet.guard({
label: "order.looked-up",
rules: [
promptScan(orderNumber),
lookupLimit({ key: userId, requested: 1 }),
],
});
if (decision.conclusion === "DENY") {
throw new Error(`Denied: ${decision.reason}`);
}
return await db.orders.find(orderNumber);
}

The same call in Python, where guard() has a guard_sync() pair:

import os
from arcjet.guard import launch_arcjet, DetectPromptInjection
aj = launch_arcjet(key=os.environ["ARCJET_KEY"])
prompt_scan = DetectPromptInjection()
decision = await aj.guard(
label="order.looked-up",
rules=[prompt_scan(order_number)],
)
if decision.conclusion == "DENY":
raise RuntimeError(f"Denied: {decision.reason}")

Labels are slugs: lowercase letters, digits, dash, underscore, and dot. They must start and end with a lowercase letter or digit. Uppercase is rejected, so use tools.get-weather or tools.get_weather, not tools.getWeather. Hardcode them rather than building them from user input, so they stay greppable and the Console can group by them.

The JavaScript guard client is async and has no blocking variant. Python has a _sync pair for every entry point (launch_arcjet_sync(), guard_sync()), which is what a queue worker or other synchronous job needs. Go guard rule constructors require Mode (ModeLive or ModeDryRun), and an empty Mode returns ErrInvalidMode. HTTP Protect rules default an empty Mode to ModeDryRun.

For complete, copy-paste examples for every framework, including the rule parameter reference and decision API, see llms-full.txt. llms.txt is a shorter index that links out to the full reference.

App typeRules
AI or LLM chatshield + detectBot + tokenBucket + sensitiveInfo + detectPromptInjection
Public APIshield + detectBot + fixedWindow or tokenBucket
Signup or login formshield + detectBot + validateEmail + slidingWindow
Internal or admin routeshield + filter (country/VPN blocking)
Any web appshield + detectBot (good baseline)
AI agent tool call (Guard)tokenBucket + detectPromptInjection + localDetectSensitiveInfo
MCP tool handler (Guard)tokenBucket (keyed by session) + detectPromptInjection
Queue worker or background job (Guard)tokenBucket (keyed by user) + detectPromptInjection + localDetectSensitiveInfo
Claude Managed Agents (Guard)tokenBucket + detectPromptInjection + localDetectSensitiveInfo on inbound user.message and custom tools

localDetectSensitiveInfo detects EMAIL, PHONE_NUMBER, IP_ADDRESS, and CREDIT_CARD_NUMBER with the bundled detector, entirely on-device. Names, addresses, and government or financial identifiers need the Rampart backend. Pass backend: rampart() on the rule, or sensitiveInfoBackend: rampart() on the client to cover the sensitive information rule in a remote policy too.

The hooks Claude Code, GitHub Copilot, OpenAI Codex, and Cursor already fire can call Arcjet before every tool call, with no SDK and no code change. An administrator installs one hook entry per event and publishes the policies to enforce. For the hook configuration and the starter policies, see Secure coding agents.

A policy decides the action for a guard call, and it’s managed outside the application, so it changes without a deployment. Policies are MCP-only: the CLI has no policy commands.

A direct guard() call selects a policy with label. A framework adapter takes action instead, for the same slug. Passing label to guardTool() doesn’t compile.

  1. Call list-guard-policies to see the site’s policies and their labels.
  2. Call get-guard-policy for the policy’s contract: its label, and every input with its kind and exposure. Write the guard() call from that contract. A policy does nothing until the application sends values under exactly the names it declares, and a mistyped name produces a policy that silently never fires.
  3. To create one, call describe-guard-policy with a Guard label and a description of what the action must refuse, then validate-guard-policy to compile it and run its stored tests, then put-guard-policy to publish.

A coding agent policy is selected by what it executes on rather than by a label, and its inputs are fixed. Pass describe-guard-policy a draft that already carries the contract and the execute-on setting, or copy a starter policy from Coding agent policies.

A policy’s conditions are Rego over the declared inputs, and they can read Arcjet’s own detector findings as facts. A policy with a live expression rule needs at least one stored test before it can publish. A policy whose rules are all dry run can be saved without tests, and detector-backed rules are exempt. For more information, see Author and publish policies.

Every framework adapter takes actor and inputs, in both JavaScript and Python, each as a value or a function resolved per call. Build each input with policyInput, which makes the wire type and the exposure explicit:

inputs: {
recipient: policyInput.server.string(recipient),
allowed_recipients: policyInput.server.stringList(allowlist),
body: policyInput.local.string(body),
}

server values are transmitted to Arcjet. local values stay in SDK memory and only a SHA-256 digest is sent. Derive actor from an authenticated server-side identity and never from user-controlled input, because a policy can be conditioned on it. For what a resolver receives in each adapter, see Send an actor and policy inputs.

After adding protection and starting the app:

  1. Exercise the protection site. Send a test request to a protected route, or for guards, invoke the protected tool or task. A small script that calls the function twice, once to allow and once to exceed a limit, is enough. For MCP servers, send a tool call with the MCP client or inspector.

  2. Read the decision your code received. Every guard decision has an id (prefix gdec_), a conclusion, and per-rule results. Log it.

  3. For request-based protection, list and inspect decisions from the terminal:

    Terminal window
    arcjet requests list --site-id site_01abc123
    arcjet requests details --site-id site_01abc123 --request-id <request-id>
    arcjet requests explain --site-id site_01abc123 --request-id <request-id>
    arcjet analyze traffic --site-id site_01abc123

    The equivalent MCP tools are list-requests, get-request-details, explain-decision, and analyze-traffic.

  4. For guard decisions, check the Arcjet Console. The CLI and MCP request commands cover request-based protection only, so there is no terminal equivalent for guards.

If decisions aren’t appearing, verify that ARCJET_KEY is set and that protect() or guard() is actually being called. On JavaScript and Python, check ARCJET_ENV too. For Claude Managed Agents, confirm guardEvents or guard_events ran before events.send, and that guardCustomTool or guard_custom_tool ran before each custom tool.

These prompts work well when given to an AI coding agent with skills installed and either the CLI or the MCP server connected:

  • “Set up Arcjet security for my app” adds shield, bot detection, and rate limiting end to end.
  • “Protect my API routes with Arcjet” adds shield, bot detection, and rate limiting to all API routes.
  • “Add prompt injection detection to my AI chat endpoint” adds detectPromptInjection with message scanning.
  • “Block sensitive data from reaching my LLM” adds sensitiveInfo in JavaScript, or detect_sensitive_info in Python, to scan for personal information.
  • “Rate limit my AI agent tool calls per user” wires up tokenBucket keyed by user inside each tool handler.
  • “Secure my MCP server” adds per-tool guard() calls with hardcoded labels and session-scoped rate limits.
  • “Protect my queue worker from prompt injection” uses the Python synchronous guard client (launch_arcjet_sync) with prompt injection detection on job payloads.
  • “Block personal information in agent tool outputs” uses localDetectSensitiveInfo on tool results, so data in tool outputs doesn’t leak back into the model context.
  • “Only let this agent email approved recipients” declares recipient and allowed_recipients inputs on an email.sent policy and generates the Rego that denies anything else.
  • “Show me the policy behind this guard label” calls get-guard-policy and writes the guard() call from the contract it returns.
  • “Give me a security briefing for my site” calls get-security-briefing over MCP, or arcjet briefing --site-id <id> from the CLI.
  • “What would happen if I promote my dry-run rules to live?” calls get-dry-run-impact to show blocked requests, affected IPs, and false-positive risk.
  • Quick start guide for framework-specific setup with full code examples
  • Guards to protect tool calls, queues, and agentic pipelines without an HTTP request
  • Claude Managed Agents agent guard for inbound user.message and custom tools in Anthropic’s hosted harness
  • Arcjet CLI to manage sites, keys, and rules from the terminal
  • MCP server for the full MCP tool reference and client setup
  • Arcjet plugin, a bundled install that wires up MCP, skills, and coding rules together for Claude Code and Cursor users. It’s an alternative to the steps in this guide, not an additional step.
  • llms.txt, a short machine-readable index for AI agents
  • llms-full.txt, the full machine-readable reference with all framework examples, rule parameters, and the decision API
  • Request remote rules to manage request rules from the Console or the MCP server without code changes
  • Policy contract for labels, actors, typed inputs, detectors, and rules
  • Write policies in Rego for the input document, the supported language subset, and what it excludes
  • Policy examples for worked policies covering email, refunds, web fetch, databases, files, and budgets
  • Observe agent activity to ingest agent activity with no code change
  • Best practices for recommended patterns and anti-patterns