PreToolUse hooks first, so a policy can deny built-in and MCP tools, and UserPromptSubmit can block a prompt. OpenAI Agents SDK has no inbound hook, and Arcjet gates its authored function tools, not hosted tools, MCP, or handoffs.How do OpenAI Agents SDK and Claude Agent SDK differ on security?
OpenAI Agents SDK and Claude Agent SDK are the first-party agent SDKs from OpenAI and Anthropic, and they differ most in which hook can still refuse a side effect. Claude Agent SDK runs every tool call through PreToolUse hooks first, so a policy can deny built-in tools such as Bash and Write and MCP tools that you didn't write, and UserPromptSubmit can block a prompt before the model sees it. OpenAI Agents SDK has no inbound hook, and its tool guardrails cover function tools and local MCP servers but not hosted tools or handoffs. Arcjet ships an adapter for both SDKs in JavaScript and Python, so one centrally managed policy decides in the path of each tool call on either stack. Choose Claude Agent SDK if you need to deny built-in or MCP tools, and choose OpenAI Agents SDK if the side effects that matter are function tools that you wrote.
Arcjet publishes this comparison. SDK details come from the Claude Agent SDK documentation and the OpenAI Agents SDK documentation, reviewed on September 25, 2026.
OpenAI Agents SDK and Claude Agent SDK are built differently. Claude Agent SDK is Claude Code as a library: it gives your application the same built-in tools, agent loop, permissions, and hooks that power Claude Code. OpenAI Agents SDK is a small set of primitives – agents, tools, handoffs, agents used as tools, and guardrails – that you compose, plus sandbox and voice agents. Helper names don't carry across, so the Arcjet OpenAI Agents adapter doesn't export guardHooks. For the series hub, see Agent framework security.
What can Claude Agent SDK deny?
Claude Agent SDK can deny built-in tools, MCP tools, and inbound prompts, because it checks every tool request in a fixed order that starts with hooks. According to its permissions documentation, the order is hooks first, then deny rules, ask rules, the permission mode, allow rules, and finally the canUseTool callback. A PreToolUse hook that denies applies even in bypassPermissions mode, and a hook that allows doesn't skip the deny and ask rules.
The same permissions page warns that a call approved by an allow rule or a permission mode never reaches canUseTool, so a check placed there is silently bypassed for that tool.
Arcjet attaches to those hooks. guardHooks({ inbound }) screens inbound text on UserPromptSubmit, and on DENY the hook blocks the prompt, which the Claude Code hooks reference describes as blocking prompt processing and erasing the prompt. In version 2.1.208 and later, a UserPromptSubmit hook that times out also blocks the prompt, according to the Agent SDK hooks guide.
The Arcjet guardHooks helper also denies unwrapped built-in and MCP tools on PreToolUse, and guardTool wraps an authored tool() so that its handler never runs on DENY. PostToolUse is capture only and can't undo a tool that already ran. For more information about the permission trap, see canUseTool is not a policy gate.
In JavaScript, import from @arcjet/guard/claude-agent-sdk/v0. In Python, import guard_hooks and guard_tool from arcjet.guard.claude_agent_sdk. The Python guard_hooks registers only the hooks that you ask for, so passing inbound alone leaves tool calls ungated, while the JavaScript guardHooks always registers PreToolUse, UserPromptSubmit, and PostToolUse.
The Claude Agent SDK helpers default to onGuardError: "deny". Setting onGuardError to "allow" is a legitimate choice on inbound UserPromptSubmit, because failing closed there stops the agent answering. For the implementation steps, see How to screen inbound prompts in Claude Agent SDK and Claude Agent SDK security.
What can OpenAI Agents SDK deny?
OpenAI Agents SDK can deny function-tool calls through its own guardrails, and Arcjet can deny authored function tools on it, but neither reaches hosted tools or handoffs. According to its guardrails guide, input guardrails run only for the first agent and run in parallel with it by default, output guardrails run only for the agent that produces the final output, and tool guardrails run around each function-tool invocation, including tools from local MCP servers that configure them. The guide states that handoffs, hosted MCP tools, other hosted tools, and the built-in computer, shell, and apply-patch tools don't use the tool-guardrail pipeline.
Arcjet has no inbound hook to attach to on OpenAI Agents SDK, so you screen user text with a direct guard() call before the run and skip the run on DENY. A direct guard() call fails open, so check hasFailedOpen() where that site must fail closed.
For tools, the JavaScript guardTool from @arcjet/guard/openai-agents/v0 wraps FunctionTool.invoke, and the Python guard_tool from arcjet.guard.openai_agents attaches as a tool_input_guardrails entry and denies with reject_content(...). The authored handler is the only local side effect that the Arcjet adapter can stop.
Hosted tools, MCP servers, handoffs, agents used as tools, and computer and shell tools aren't Arcjet deny points, and Realtime and Sandbox are outside the adapter. Runner tool-start events are observe-only. needsApproval and hosted MCP requireApproval are human holds rather than policy. For more information, see How do I secure an OpenAI Agents SDK agent?.
How do the two SDKs compare on each security job?
Claude Agent SDK and OpenAI Agents SDK match on authored-tool deny and on adapter languages, and they differ on inbound screening, built-in and MCP deny, and the human-in-the-loop (HITL) trap. The following table compares the two SDKs on six jobs.
| Job | Claude Agent SDK | OpenAI Agents SDK |
|---|---|---|
| Inbound screen with Arcjet |
| A direct |
| Authored-tool deny with Arcjet |
|
|
| Built-in and MCP deny with Arcjet |
| None. Hosted tools, MCP, handoffs, and agents used as tools aren't Arcjet deny points |
| Languages with an Arcjet adapter | JavaScript and Python | JavaScript and Python |
| HITL trap |
|
|
| SDK-owned controls | Permission modes, allow and deny rules, and hooks | Input, output, and tool guardrails. See OpenAI guardrails vs Arcjet |
On both stacks, protect() is the check for HTTP routes and guard() is the check inside the agent. Don't construct a fake Request inside a tool to reach protect(), and don't expect bot detection on the agent path, because it runs only on protect().
When do you choose Claude Agent SDK or OpenAI Agents SDK?
Choose Claude Agent SDK when you need a deny on Bash, Write, or an MCP tool that you didn't write. The Claude PreToolUse hook sees those calls before any permission rule, so an Arcjet policy there still applies when the permission mode would otherwise approve the call.
Choose OpenAI Agents SDK when the side effects that matter are authored function tools that you own, and you can write the inbound screen before the run yourself. Plan for hosted tools, MCP, and handoffs to stay outside an Arcjet deny, and keep resource-level authorization in the services those tools reach.
If your team runs both, use the adapter that matches each SDK rather than copying helper names across. Human approval is not a security policy covers the Claude approval callback, and needsApproval and LangGraph interrupt() are not a security policy covers OpenAI needsApproval. The same Arcjet policy model also covers the coding agents your developers run, including Claude Code and OpenAI Codex, through their hooks. For more information, see how to secure AI coding agents.
Frequently asked questions
How do OpenAI Agents SDK and Claude Agent SDK differ on security?
Claude Agent SDK runs every tool call through PreToolUse hooks before any permission rule, so a policy can deny built-in and MCP tools, and UserPromptSubmit can block a prompt. OpenAI Agents SDK has no inbound hook, so you screen text with a direct guard() call before the run, and Arcjet gates authored function tools only.
Can OpenAI Agents deny MCP tools the way Claude Agent SDK can?
Not through Arcjet. Claude PreToolUse through guardHooks can deny MCP tools that you didn't wrap. On OpenAI Agents, the Arcjet adapter gates authored function tools only, and OpenAI's own tool guardrails can attach to local MCP servers but not to hosted tools or handoffs.
Where does each SDK screen inbound text?
Claude Agent SDK screens inbound text on UserPromptSubmit through guardHooks({ inbound }), and on DENY the hook blocks the prompt before the model sees it. OpenAI Agents SDK has no inbound hook, so screen with a direct guard() call before the run. A direct guard() call fails open, while the Claude helpers default to deny.
Is canUseTool the same as needsApproval?
Yes, in kind: canUseTool and needsApproval are both a pause for a person, not a policy. Claude documents that a call approved by an allow rule or permission mode never reaches canUseTool. OpenAI needsApproval and hosted MCP requireApproval pause the run for a person.
Does Arcjet support both SDKs in Python?
Yes. Both Arcjet adapters ship in JavaScript and Python. Import from @arcjet/guard/claude-agent-sdk/v0 or arcjet.guard.claude_agent_sdk for Claude Agent SDK, and from @arcjet/guard/openai-agents/v0 or arcjet.guard.openai_agents for OpenAI Agents SDK. One difference matters in Python: guard_hooks registers only the hooks that you ask for, so passing inbound alone leaves tool calls ungated.
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.