How do agent frameworks differ on security?
Agent frameworks differ on which hook can still refuse a side effect. Eve, Mastra, Claude Agent SDK, OpenAI Agents SDK, LangGraph JS, and LangChain Python each expose a different inbound path, a different authored-tool deny, and a different answer for MCP or unwrapped tools. A helper-name matrix hides that.
This page is the series hub. Each row is a job: inbound screen, authored-tool deny, unwrapped or MCP deny, and the human-in-the-loop trap. The dedicated How-tos name the helper. For more information about the vendor-layer map, see AI agent security platforms. This page is the runtime map.
A team that ships Eve, then Mastra, then OpenAI Agents often copies the last helper name into the next repo. guardInbound exists on Eve. It doesn't exist on OpenAI Agents or LangGraph. guardHooks exists on Mastra and Claude. It doesn't exist on LangGraph. The row that matters is the job, not the identifier.
What does each stack deny?
Each stack in the following table can refuse work at the row's job only if that hook exists. A blank MCP cell means the adapter has no deny on tools that you didn't write.
| Stack | Inbound screen | Authored-tool deny | Unwrapped / MCP deny | HITL trap |
|---|---|---|---|---|
| Eve |
|
|
| onAllow: "user-approval" |
| Mastra |
|
|
| requireApproval |
| Claude Agent SDK |
|
|
|
|
| OpenAI Agents SDK | Direct |
| None. Hosted tools, MCP, handoffs, and |
|
| LangGraph JS | Direct |
|
| interrupt() |
| LangChain Python | Application |
| Only tools you named in a | A human callback you add. |
The Vercel AI SDK is the other published JavaScript wrapper: guardTool plus createAgentContext plus aiToolsContext. It isn't a separate inbound host. For more information about that wrapper, see How do I secure a Vercel AI SDK agent?.
What is the HITL trap on each stack?
Human-in-the-loop parks a call. It doesn't decide the call. Eve user-approval, Mastra requireApproval, and Claude canUseTool are on Human approval is not a security policy. OpenAI needsApproval, hosted requireApproval, and LangGraph interrupt() are on needsApproval and LangGraph interrupt() are not a security policy.
A reviewer who clicks through lookups and one refund has approved the send. The model already saw the prompt. Screen inbound text first. Deny the tool or connection before the host is called. Then park the few irreversible allows.
What happens on each stack when Guard is unavailable?
Every wrapper fails closed when the policy can't be evaluated, but each stack reports it differently, and that shape decides what your error handling looks like. A denial means the policy said no. Unavailable means the check never ran.
On the Vercel AI SDK the tool doesn't execute and the model receives a retryable denial result with reason ERROR. LangChain Python is the most explicit: guard_tool raises ArcjetToolUnavailableError against ArcjetToolDeniedError, while guard_action and ArcjetMiddleware raise ArcjetUnavailableError against ArcjetDeniedError. Eve, Mastra, Claude Agent SDK, LangGraph, and OpenAI Agents helpers all default to onGuardError: "deny". OpenAI Agents guardTool is the odd one: it returns a plain ArcjetDenialResult and never throws, so the denial arrives in the payload rather than as an error.
Inbound is the one place where "allow" is defensible on every stack, because failing closed there stops the agent answering at all during an outage. Set it deliberately, per call site, and never on the tool that sends. Direct guard() is different again: it fails open by construction and reports it on hasFailedOpen(), so an inbound screen that only checks for DENY starts the agent during an outage.
Which learn page do I read?
Start with the inbound recipe on the host that you ship, then the unwrapped-tool recipe if the host call is the risk.
Eve: How to detect prompt injection in an Eve agent and How to secure Eve MCP connections. Mastra: How to secure a Mastra agent and How to secure Mastra MCP tools. Claude: How to screen inbound prompts in Claude Agent SDK and How to block Bash in Claude Agent SDK. OpenAI Agents: How do I screen inbound prompts in OpenAI Agents SDK?. LangGraph: How do I secure MCP tools in LangGraph?. LangChain Python: How do I secure a LangChain Python agent?. Vercel AI SDK: How do I secure a Vercel AI SDK agent?.
How do I pick a starting check?
If the host has a channel or submit hook, screen that text before the turn starts. If you wrote the tool, wrap it. If the host invokes MCP or a built-in that you didn't write, use the unwrapped deny for that host, or accept that OpenAI Agents has none.
protect() is HTTP. guard() is tools, MCP, and any path with no Request. Direct guard() fails open. Wrappers default to deny. Don't mint a fake Request. Guard doesn't detect bots.
OpenAI Agents inputGuardrails are SDK tripwires, not this table. For more information about that split, see OpenAI Agents guardrails vs Arcjet. For more information about the two first-party SDKs, see OpenAI Agents SDK vs Claude Agent SDK. Adapter docs live under framework integrations.
Frequently asked questions
How do agent frameworks differ on security?
They differ on which hook can still refuse a side effect. Eve, Mastra, Claude Agent SDK, OpenAI Agents SDK, LangGraph JS, and LangChain Python each expose a different inbound path, a different authored-tool deny, and a different answer for MCP or unwrapped tools.
Which stack can deny MCP or unwrapped tools?
Eve uses guardApproval on the connection. Mastra uses guardHooks on beforeToolCall. Claude uses PreToolUse. LangGraph JS uses guardToolNode. LangChain Python only denies tools that you named in a ToolPolicy. OpenAI Agents has no MCP or hosted deny.
Is human approval a policy on any of these stacks?
No. Eve user-approval, Mastra requireApproval, Claude canUseTool, OpenAI needsApproval, hosted requireApproval, and LangGraph interrupt() park a call. They don't decide it.
Where do I start on the host I ship?
Read the inbound recipe first, then the unwrapped-tool recipe if the host call is the risk. This page links each dedicated /learn how-to. The vendor-layer map is AI agent security platforms.
Does Guard detect bots on these agent paths?
No. Bot detection is an HTTP control on protect(). guard() is the check on tools, MCP, and paths with no Request. Don't mint a fake Request.
What happens when Guard is unavailable on each stack?
Every wrapper fails closed. Vercel AI returns a retryable denial with reason ERROR. LangChain Python raises ArcjetToolUnavailableError or ArcjetUnavailableError. Eve, Mastra, Claude, LangGraph, and OpenAI Agents default to onGuardError: "deny". Direct guard() fails open and reports it on hasFailedOpen().
AI runtime security in your code
Protect your AI agent workflows with Arcjet
Arcjet runs inside your application, where it can use runtime context to enforce agent actions and budgets, detect prompt injection, and protect sensitive information before a workflow acts.