integrate-arcjet-guard-strands-agents-pylisted
Install: claude install-skill arcjet/arcjet-plugin
# Integrate Arcjet Guard into Python Strands Agents
`arcjet.guard.strands_agents` 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 Strands-specific.
Official Python `strands` / `strands-agents>=1.11.0,<2` only — not JS
`@arcjet/guard/strands-agents/v1` (docs
https://docs.arcjet.com/guards/strands-agents/), not community forks.
Importing `arcjet.guard.strands_agents` does not load LangChain, CrewAI,
or JS `@arcjet/guard/strands-agents/v1`. Unlike CrewAI (no extra), the
`arcjet[strands-agents]` extra exists at the pin
(`strands-agents = ["strands-agents>=1.11.0,<2"]` in `pyproject.toml`).
The extra is safe (no chromadb).
Exports: `guard_tool`, `guard_hooks`, `strands_agent_context`. Authored
`@tool` plus `Agent(hooks=)` / `add_hook`.
Three surfaces, one decision rule:
- **An authored `@tool`** → `guard_tool`. Hand the agent the copy this
returns — the original stays unguarded.
- **Unwrapped / MCP tools** → `guard_hooks`. Gate is per-tool
`BeforeToolCallEvent.cancel_tool` (`True` or `str`). Already-wrapped
tools are skipped so Guard is not called twice.
- **Correlation** → `strands_agent_context` reads a caller-owned id from
`invocation_state`. It never mints. It never reads `trace_id`.
Docs: https://docs.arcjet.com/gu