arcjet/arcjet-js/integrate-arcjet-guard-claude-managed-agents
Claude Code and agent skill by arcjet/arcjet-js
- community
Checking that the SKILL.md file is still in the repository.
Integrate Arcjet security into Claude Managed Agents (hosted REST+SSE, beta managed-agents-2026-04-01) using @arcjet/guard — screen user.message / initial_events before sessions.events.send, and gate custom tools on agent.custom_tool_use. Use when asked to add Arcjet to Claude Managed Agents, rate limit custom tools, or block prompt injection on hosted sessions. Not the Claude Agent SDK.
Install
npx vskill@latest install arcjet/arcjet-js/integrate-arcjet-guard-claude-managed-agentsSKILL.md
Integrate Arcjet Guard into Claude Managed Agents
@arcjet/guard's Claude Managed Agents v0 namespace wraps the agent's existing Arcjet client. It never talks to the Arcjet API itself. Anthropic runs the hosted tool loop. There is no PreToolUse.
This is not @arcjet/guard/claude-agent-sdk/v0. Do not reuse that adapter, its hooks, or guardTool.
- Inbound text (
user.message/initial_events) →guardEvents()
before sessions.events.send. DENY does not send. There is no guardInbound.
- A custom tool you execute (
agent.custom_tool_use) →
guardCustomTool(). DENY does not run the tool; send user.custom_tool_result with is_error: true and error text (that field exists on the real events API). Self-hosted EnvironmentWorker / betaTool({ run }) uses the same gate. The CLI worker cannot register custom tools.
- Correlation →
claudeManagedAgentsContext()is caller-owned only.
It never mints. It never treats Anthropic session/event ids as if we created them. Never traceId.
What cannot be gated
Default permission_policy: always_allow cannot be gated. Anthropic executes bash/read/write in the cloud sandbox before your process sees an event. web_search / web_fetch always run on Anthropic. MCP: Anthropic is the client; customer-side Guard is on custom tools and MCP servers you host. user.tool_confirmation is HITL (always_ask), not a policy gate — do not add a confirmation helper as the happy path. Same trap as Cloudflare Think needsApproval.
protect() stays fail-open. These helpers are fail-closed.
Docs: https://docs.arcjet.com/guards/claude-managed-agents/ (shared JS+Python page). Do not edit /guards/claude-agent-sdk/ or /guards/claude-agent-sdk-py/.
Questions to ask the human first
Ask only what you cannot infer from the code; suggest defaults.
- Which custom tools does the app execute on
agent.custom_tool_use?
Those get guardCustomTool. Built-ins under always_allow cannot.
- What limits? (e.g. "10 lookups/min per order" →
tokenBucket.) - Who is the user for metadata — an opaque user/tenant ID (never PII)?
Default: none. Session/event ids from Anthropic are not the correlation id.
- Is an Arcjet outage unacceptable? Every helper defaults to
onGuardError: "deny", which also decides a call whose rules or metadata callback threw or returned a value Guard cannot use: Guard is still called without that value, and a DENY stands. Ask explicitly about inbound guardEvents: failing closed there means the turn is not sent.
The things readers get wrong
- This is not the Claude Agent SDK. No
guardTool, noguardHooks,
no PreToolUse, no UserPromptSubmit. Do not also wrap with @arcjet/guard/claude-agent-sdk/v0 or @arcjet/guard/vercel-ai/v7.
- There is no `guardInbound`. The helper is
guardEvents. - The import path is versioned and there is no alias.
@arcjet/guard/claude-managed-agents/v0. @arcjet/guard/claude-managed-agents does not resolve. There is no /v1.
- Correlation is caller-owned, never minted. Do not pass
session.id / event ids to claudeManagedAgentsContext as if Arcjet created them. Never traceId.
- Default `always_allow` cannot be gated. Do not claim we can block
Anthropic-cloud bash/read/write.
- On custom-tool DENY, send `user.custom_tool_result`. Do not invent
fields the schema lacks. is_error exists — use it. Do not run the tool. On ALLOW, the caller must still send the success result or the session idles.
- **Do not mix a gated user turn with a tool result in one send unless
you mean to.** guardEvents will still forward non-user.message events when the turn is denied, so a batched user.custom_tool_result is not dropped. Prefer sending tool results on their own.
- Do not add a `claude-managed-agents` example in this SDK repo.
Examples belong in arcjet/examples.
Step 1: Install and find the guard client
Install @arcjet/guard (required), plus @anthropic-ai/sdk (optional peer, needed for types). Always use the versioned path.
If the agent has no guard client yet, launch one once at module scope:
Step 2: Screen inbound before sessions.events.send
The same helper gates sessions.create({ initial_events }) — pass those events and send them only on ALLOW.
To screen PII in the same text, add localDetectSensitiveInfo({ backend: rampart() })(text) to inbound.rules. rampart comes from @arcjet/sensitive-info-rampart, which detects PII on-device in your app process before anything is sent to Anthropic.
Step 3: Gate custom tools you execute
Self-hosted: wrap betaTool({ run }) with the same guardCustomTool (pass the tool as the second argument). The CLI worker cannot register custom tools.
Optional actor and inputs (static, or a resolver over this adapter's native call — parsed input plus trusted runtime/context) are forwarded on the guard call so a remote policy that declares those names can evaluate. Build each input with policyInput. A resolver that throws or returns a value Guard cannot use is left out of the guard call, and onGuardError decides.
Step 4: Correlation
Mint (or load) a conversation id the app owns. Pass it to claudeManagedAgentsContext({ correlationId }). Do not use Anthropic session.id or event ids as if Arcjet created them. If the id is missing or invalid, the call is uncorrelated rather than joined to a generated id nobody has.
Verify the integration
npm run typecheckpasses.- Exercise inbound PI (send is not called), a custom-tool deny (execute
is not called; user.custom_tool_result with is_error: true is sent), a rate limit, and fail-closed (an unreachable guard).
- Confirm in the Arcjet dashboard that decisions share the caller-owned
conversation id — not an Anthropic session/event id you did not pass.
- Manual E2E with a real
ARCJET_KEYis still-to-verify until you run it.
A full working demo belongs in `arcjet/examples` (follow-up; do not add an example under examples/ in the JS SDK repo).
Note: capture events are fire-and-forget and batched, so events can lag the decisions they accompany by a few seconds. A dropped event is diagnosed, never thrown.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingarcjet-guard/skills/integrate-arcjet-guard-claude-managed-agents/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/arcjet/arcjet-js/integrate-arcjet-guard-claude-managed-agents)