Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Integrate Arcjet Guard Crewai

ASecurity

Integrate Arcjet Guard into official CrewAI — register process-wide PRE_TOOL_CALL with register_arcjet_hooks, or wrap a standalone BaseTool you call yourself with guard_tool. Use when asked to add Arcjet to CrewAI, LiteAgent, crew-injected tools, rate limit those tools, screen inbound messages before kickoff, or block prompt injection / PII. Official crewai only; not an npm CrewAI port and not LangChain Crew wrappers.

3 stars
0 votes
0 copies
0 views
Added 9/23/2026
ai-agentspythongobashgitapi

Works with

cliapimcp

Security Analysis

A96/100
mediumInstalls packages at runtime which could introduce malicious dependencies

Scanned 9/23/2026

Install to Claude Code

$npx -y skills add arcjet/skills --skill integrate-arcjet-guard-crewai --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Integrate Arcjet Guard Crewai?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Integrate Arcjet Guard Crewai
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/arcjet-integrate-arcjet-guard-crewai/badge)](https://www.skillsdirectory.com/skills/arcjet-integrate-arcjet-guard-crewai)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: integrate-arcjet-guard-crewai
description: Integrate Arcjet Guard into official CrewAI — register process-wide PRE_TOOL_CALL with register_arcjet_hooks, or wrap a standalone BaseTool you call yourself with guard_tool. Use when asked to add Arcjet to CrewAI, LiteAgent, crew-injected tools, rate limit those tools, screen inbound messages before kickoff, or block prompt injection / PII. Official crewai only; not an npm CrewAI port and not LangChain Crew wrappers.
license: Apache-2.0
compatibility: Requires Python >= 3.10, official crewai>=1.15.3,<2 installed by the user, PyPI arcjet 1.0.0+, and a blocking Guard client (launch_arcjet_sync). There is no arcjet[crewai] extra.
metadata:
  author: arcjet
  type: core
  library: arcjet
---

# Integrate Arcjet Guard into CrewAI

`arcjet.guard.crewai` wraps the agent's existing Arcjet client. It never
talks to the Arcjet API itself. Shared Guard fundamentals (client, rules,
labels, decisions, capture, registration) live in
[../arcjet/references/guards_python.md](../arcjet/references/guards_python.md).
Load that reference for anything that is not CrewAI-specific.

Official `crewai` only — not community forks, not LangChain Crew wrappers,
not an npm CrewAI port. There is **no** `arcjet[crewai]` extra: CrewAI
hard-depends on `chromadb`, which carries unpatched RCE CVE-2026-45829,
so an Arcjet extra must not pull it in. Install CrewAI yourself. Importing
`arcjet.guard.crewai` does not load LangChain.

Exports: `register_arcjet_hooks`, `unregister_arcjet_hooks`,
`ArcjetCrewAIHooks`, `guard_tool`, `ToolPolicy`, `sanitize_tool_name`,
`free_text_arguments`. There is no `guard_crew`.

Two surfaces, one decision rule:

- **A tool a crew, LiteAgent, MCP adapter, or crew-injected list executes**
  → `register_arcjet_hooks` + `ToolPolicy`. Gate is process-wide
  `PRE_TOOL_CALL` only. DENY raises `HookAborted(reason=..., source="arcjet")`.
- **A CrewAI `BaseTool` you call yourself** → `guard_tool`. This is the
  **only** CrewAI path that raises `ArcjetDeniedError` /
  `ArcjetUnavailableError`. `BaseTool.run` never dispatches
  `PRE_TOOL_CALL`.

Docs: https://docs.arcjet.com/guards/crewai/.

## The gate is process-wide `PRE_TOOL_CALL`, once

`register_arcjet_hooks` registers on CrewAI's dispatcher. A `DENY` (or
unevaluated Guard under the default `on_guard_error="deny"`) raises
`HookAborted(reason=..., source="arcjet")` so the tool never runs. CrewAI
swallows every other exception — raising `ArcjetDeniedError` /
`ArcjetUnavailableError` from the hook would *run* the tool. The hook
path is **sync only** — pass `launch_arcjet_sync` / `ArcjetGuardSync`. An
async client is refused at registration (`ArcjetMisconfiguration`). A
second `register_arcjet_hooks` in the same process is also
`ArcjetMisconfiguration` (CrewAI's registry appends and would
double-evaluate); call `unregister()` on the handle first.

## `POST_TOOL_CALL` is never registered

Only PRE is installed. The decision is captured in PRE. POST is not a
policy surface. The agent always sees
`Tool execution blocked by hook. Tool: {name}`. `HookAborted.reason` is
telemetry only. A proceed still records `success` — do not read CrewAI
hook capture as the five-value `metadata.outcome` table used by
`guard_action` / LangChain helpers.

## `human_input` is not a policy gate

Agent/Task `human_input` and `request_human_input` are human-in-the-loop.
Same trap as JS `humanInTheLoopMiddleware`, LangGraph `interrupt()`,
OpenAI Agents `needsApproval`, and Genkit `interrupt()`. There is no
inbound helper and no approval helper.

## Questions to ask the human first

Ask only what you cannot infer from the code; suggest defaults.

1. Which tools are **risky** (external side effects, irreversible, spends
   money, sends messages)? Crew-executed tools get
   `register_arcjet_hooks`. A standalone `BaseTool` you invoke yourself
   gets `guard_tool`.
2. What **limits**? (e.g. "10 lookups/min per user" → `TokenBucket`.)
3. Who is the **user** for metadata — an opaque user/tenant ID (never PII)?
   Default: none. Crew, task, and agent names are metadata, never minted
   into a correlation id. Use a caller-owned `correlation_id` /
   `arcjet_sequence`.
4. Is an Arcjet outage unacceptable? Every helper defaults to
   `on_guard_error="deny"`. Ask explicitly about inbound screening before
   `crew.kickoff`: failing closed there means the crew does not run, so
   `"allow"` is a routine and legitimate choice at that one call site.

## The things readers get wrong

1. **There is no `arcjet[crewai]` extra.** Install `crewai>=1.15.3,<2`
   yourself. `arcjet.guard.crewai` ships in PyPI `arcjet` 1.0.0.
2. **There is no `guard_crew`.** Use `register_arcjet_hooks`.
3. **The hook path is sync only.** Pass `launch_arcjet_sync`.
4. **Raise `HookAborted` from the hook, not Arcjet errors.** CrewAI
   swallows anything else and the tool runs.
5. **`human_input` is HITL, not policy.**
6. **Screen inbound with core `guard` / `guard_sync` before
   `crew.kickoff`.** Core `guard()` fails open.
7. **Key rate limits on the authenticated caller**, not a model-supplied
   order id. `sanitize_tool_name` matches `Send Email` and `send_email`.
8. **Do not hand-wrap every CrewAI tool with raw `guard()`.**
9. **`inputs=` is accepted.** The hook resolver is `(arguments, ctx)`.
   A missing decision is not a denial — verify in Console/CLI.

## Step 1: Install and find the guard client

```bash
pip install arcjet
pip install "crewai>=1.15.3,<2"
```

Launch a **sync** client at module scope for the hook path:

```python
import os
from arcjet.guard import launch_arcjet_sync

aj = launch_arcjet_sync(key=os.environ["ARCJET_KEY"])
```

Use `launch_arcjet` only from async application code, or from
`guard_tool` when you call `arun()`.

## Step 2: Gate crew-executed tools — `register_arcjet_hooks`

`ToolPolicy` is `action` + `rules`, keyed by tool name. Keys and the
optional `tools=` filter go through `sanitize_tool_name` (CrewAI
1.15.3+). Tools without a matching policy still get
`"{sanitized_tool_name}.invoked"` and the registrar-level `rules` (empty
still contacts Guard) unless you pass `tools=`. `free_text_arguments`
strips opaque ids (`tool_call_id`, `*_id`, …) when you want only free
text for a scanning rule — the hook itself hands resolvers the tool's
own argument mapping unfiltered. Already-`guard_tool`-wrapped tools are
skipped so Guard is not called twice. Tear down with
`unregister_arcjet_hooks(hooks)` or `hooks.unregister()`.

```python
from crewai import Agent, Crew, Task
from arcjet.guard import DetectPromptInjection, TokenBucket, launch_arcjet_sync
from arcjet.guard.crewai import ToolPolicy, register_arcjet_hooks, unregister_arcjet_hooks

aj = launch_arcjet_sync(key=os.environ["ARCJET_KEY"])
lookup_limit = TokenBucket(
    label="order.looked-up",
    bucket="lookups",
    refill_rate=10,
    interval_seconds=60,
    max_tokens=10,
)
inbound = DetectPromptInjection()
user_id = authenticated_user_id

hooks = register_arcjet_hooks(
    guard=aj,
    policies={
        "lookup_order": ToolPolicy(
            action="order.looked-up",
            rules=[lookup_limit(key=user_id, requested=1)],
        ),
    },
    tools=["lookup_order"],
    on_guard_error="deny",
)

agent = Agent(
    role="Support",
    goal="Look up orders",
    backstory="Help the user with order status.",
    # human_input=True is HITL — not this policy gate
)
task = Task(
    description="Look up the user's order",
    expected_output="Order status",
    agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])

decision = aj.guard(
    label="message.received",
    rules=[inbound(user_text)],
)
if decision.conclusion == "DENY":
    raise RuntimeError("message blocked")
if decision.has_failed_open():
    raise RuntimeError("inbound guard unavailable")

crew.kickoff()
unregister_arcjet_hooks(hooks)
```

## Step 3: Gate a `BaseTool` you call — `guard_tool`

Hand the crew the copy this returns (it carries the brand the hook
skips). The original stays unguarded on purpose — if you pass that to a
crew, the hook still covers it. A sync call needs a blocking client; an
async call needs an awaitable one.

```python
from arcjet.guard.crewai import guard_tool

guarded = guard_tool(
    guard=aj,
    tool=lookup_order,
    action="order.looked-up",
    rules=[lookup_limit(key=user_id, requested=1)],
    on_guard_error="deny",
)
result = guarded.run(order_id=order_id)
```

## Step 4: Correlation

Use a caller-owned `correlation_id` / `arcjet_sequence`. Crew, task, and
agent names are metadata, never minted into an id. If nothing valid
remains, the call is uncorrelated rather than joined to a generated id.

## Verify the integration

1. `python -m py_compile` (or the project's type-check) passes.
2. Exercise inbound PI (before `kickoff`), a `PRE_TOOL_CALL` deny
   (`HookAborted`, agent sees `Tool execution blocked by hook. Tool:
   {name}`), a standalone `guard_tool` deny (`ArcjetDeniedError`), a
   rate limit, and fail-closed (an unreachable guard). Confirm
   `POST_TOOL_CALL` is not registered and `human_input` is never treated
   as the gate.
3. Confirm in the Arcjet Console / CLI that decisions share the
   caller-owned correlation id — not a crew/task/agent name.
4. Manual E2E with a real `ARCJET_KEY` is still-to-verify until you run it.

Do not invent a CrewAI example name in this skills repo.

Attribution

arcjetarcjet
View sourceMore from arcjet →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Ultra-compressed communication mode that cuts output tokens while keeping technical accuracy. Levels: lite, full, ultra and the wenyan variants. Use for /caveman, "caveman mode", "talk like caveman", "be brief" or "less tokens".

1074701 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

693621 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3351 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

691 votes

math-skill

A comprehensive mathematical reasoning skill for AI assistants — handles arithmetic to research-level problems with rigorous step-by-step reasoning, systematic verification, and transparent uncertainty handling

381 votes
View all in ai-agents →