Agent guard framework integrations
AI frameworks normally pass a model’s generated arguments directly to a tool’s
execute or invoke function. Arcjet’s framework integrations add a security
checkpoint between those two steps, so the remote policy evaluates every tool
attempt before the tool can create a side effect.
Use an integration when you want to protect tools without writing decision
handling around every function. The wrapper preserves the framework’s normal
tool definition and result flow, selects policy with a stable label, and maps
the actor and relevant tool arguments into policy inputs.
Vercel AI SDK
Section titled “Vercel AI SDK”The JavaScript integration supports Vercel AI SDK v7 through the versioned
@arcjet/guard/vercel-ai/v7 export.
import { launchArcjet, policyInput } from "@arcjet/guard";import { aiToolsContext, createAgentContext, guardTool,} from "@arcjet/guard/vercel-ai/v7";import { generateText, tool } from "ai";import { z } from "zod";
const arcjet = launchArcjet({ key: process.env.ARCJET_KEY! });
export async function runAgent(user: { id: string }, prompt: string) { const sendEmail = guardTool( arcjet, tool({ description: "Send an email", inputSchema: z.object({ to: z.string(), body: z.string() }), execute: ({ to, body }) => emailProvider.send({ to, body }), }), { label: "email.sent", actor: user.id, inputs: ({ to, body }) => ({ recipient: policyInput.server.string(to), body: policyInput.local.string(body), }), }, );
const tools = { sendEmail }; const context = createAgentContext();
return generateText({ model, prompt, tools, toolsContext: aiToolsContext(context, tools), });}The wrapped tool must have an execute function and cannot already declare a
contextSchema, because Arcjet uses that slot for agent context. On a policy
denial, the tool does not execute and the model receives an ArcjetDenialResult.
LangChain
Section titled “LangChain”The Python integration wraps synchronous or asynchronous LangChain tools. Install the optional dependency:
pip install "arcjet[langchain]"from arcjet.guard import launch_arcjet, local_input, server_inputfrom arcjet.guard.langchain import guard_toolfrom langchain_core.tools import tool
arcjet = launch_arcjet(key=ARCJET_KEY)
@toolasync def send_email(to: str, body: str) -> str: """Send an email.""" await email_provider.send(to=to, body=body) return "sent"
guarded_send_email = guard_tool( guard=arcjet, tool=send_email, label="email.sent", actor=lambda config: config["configurable"]["user_id"], inputs=lambda arguments, _config: { "recipient": server_input.string(arguments["to"]), "body": local_input.string(arguments["body"]), },)Use the asynchronous Guard client with ainvoke() and the synchronous client
with invoke(). Actor and input resolvers receive RunnableConfig and
validated tool arguments. Derive actor only from server-controlled
configuration. Asynchronous resolvers are supported for async tool invocations.
Denials and availability
Section titled “Denials and availability”Both wrappers default to fail closed when Guard is unavailable:
- Vercel AI does not execute the tool and returns a retryable denial result to
the model with reason
ERROR. - LangChain raises
ArcjetToolUnavailableError. A policy denial raisesArcjetToolDeniedError, or follows the wrapped tool’shandle_tool_errorbehavior when configured.
Set onGuardError: "allow" in JavaScript or on_guard_error="allow" in Python
only when executing without a complete security decision is acceptable.
See Availability and fail behavior for the direct client and wrapper differences.