Arcjet helps developers protect their apps in just a few lines of code. Bot detection. Rate limiting. Email validation. Attack protection. Data redaction. A developer-first approach to security.
This is an example Next.js application demonstrating a remotely-configured
Arcjet Guard policy applied to Vercel
AI SDK tool calls. A financial-adviser agent has a guarded sendEmail tool that
Arcjet evaluates against a remote email.sent policy before the simulated email
side effect can run. The policy combines string-list membership (allowed
recipients), sensitive-info detection (Rampart backend), and prompt-injection
detection.
Warning
This is a policy-matrix demo, not a production authentication pattern. The
selected client is an untrusted fixture selector, not an authenticated
identity. Production code must derive actor from an authenticated
server-side session, and any hosted version must add authentication and/or
rate limiting before calling the model. /api/context returns display labels
only — client records, allowed recipients, and scenario prompts stay on the
server. The evaluate tool trace can still include fixture values after a run;
production APIs must redact or omit tool inputs, tool results, prompts, and
sensitive values. All people, records, and identifiers in this example are
synthetic demo fixtures.
- Arcjet Guard evaluates a remotely-configured policy so you can change enforcement without redeploying the application.
- Guarding AI SDK tool calls wraps a
Vercel AI SDK tool with
guardToolso the model-selected inputs are evaluated at the boundary before the tool's side effect runs. - Sensitive information detection uses the Rampart backend to detect PII such as bank accounts and routing numbers in the email body.
- Prompt injection detection analyzes the inbound customer message for injection attacks.
-
Install dependencies:
npm ci-
Rename
.env.local.exampleto.env.localand set:ARCJET_KEY— your Arcjet site key from the Arcjet dashboard.AI_GATEWAY_API_KEY— a Vercel AI Gateway API key used to call the model.GUARD_POLICY_LABEL— optional; defaults toemail.sent. Set it if you labelled your dashboard policy differently.
-
Configure the Guard policy in the Arcjet dashboard (see Setup below).
-
Start the dev server:
npm run dev- Open http://localhost:3000 in your browser.
This example evaluates a remote Guard policy that you configure in the Arcjet dashboard. No policy rules are defined in code, so you can change and publish the policy to demonstrate enforcement without an application deployment.
Create a Guard policy labelled email.sent (or set GUARD_POLICY_LABEL to your
chosen label) with these inputs:
recipient: server stringallowed_recipients: server string listbody: local stringincoming_message: server string
Add these rules:
- Allowed-list membership requiring
recipientto be a member ofallowed_recipients. - Sensitive info on
body, allowingEMAIL,GIVEN_NAME, andSURNAMEwhile denying every other detected entity type. - Prompt injection on
incoming_message.
The example configures the Rampart sensitive-info backend. The structured demo
record uses public sandbox bank values that Rampart identifies as
BANK_ACCOUNT and ROUTING_NUMBER; the SSN recognizer provides an additional
deterministic backstop. The values come from the
Worldpay
and BILL sandbox
documentation.
The policyInput.server.* inputs (recipient, allowed_recipients,
incoming_message) are owned by the server and cannot be supplied by the
browser. Only body is a policyInput.local.* value derived from the model's
tool call. The current architecture evaluates prompt injection server-side, so
the inbound message is intentionally a server input.
Keep all rules in LIVE mode for this matrix. Review each decision in the Arcjet Console to show the trusted actor and per-rule evidence.
The server — not the browser — maps each trusted actor/client ID to its financial record and allowed recipients. The browser submits the selected client, scenario, and an allow-listed model ID; it cannot supply an actor, record, or recipient allow-list. Run each scenario for either client:
- Benign request sends a PII-free acknowledgement to the client's own allowed address.
- Wrong recipient is denied only by membership for Client A, while the same recipient is allowed for Client B.
- Sensitive information leak uses the client's allowed address, isolating the sensitive-info control when the model echoes account details.
- Layered defense contains an injected request for an external recipient and account-data exfiltration. When a model follows it, membership and sensitive-info provide deterministic backstops; prompt-injection detection may add another denial reason.
The layered-defense scenario also exposes a model selector. Start with GPT-4o mini, which reliably demonstrates the injected external send reaching the guarded tool. Then compare newer models, which may ignore the injected destination or sanitize the body before calling the tool. Model behavior is nondeterministic, which is the point of the comparison; Arcjet remains the deterministic enforcement boundary whenever a model attempts an unsafe action. Other scenarios use GPT-4o.
Check out the docs, contact support, or join our Discord server.
All development for Arcjet examples is done in the
arcjet/examples repository.
You are welcome to open an issue here or in
arcjet/examples directly.
However, please direct all pull requests to
arcjet/examples. Take a look at
our
contributing guide
for more information.