Skip to main content
Wrap your CrewAI Crew with the framework adapter (or let the CLI do it via --framework crewai) and run a scan against the multi-agent kickoff loop. The adapter sends each adversarial prompt through Crew.kickoff_async(inputs={"input": prompt}) and stringifies the result.

What this example tests

  • All 10 ASI categories against a CrewAI multi-agent crew at the kickoff boundary.
  • Multi-agent coordination attacks (inter-agent collusion, cross-task memory poisoning) — the adapter’s fingerprint sets is_multi_agent=True which unlocks the corresponding probes.
  • Tool-abuse probes when crew members have tools bound to them.
  • CrewAIAdapter duck-types your crew — CrewAI itself is not a runtime dependency of agent-guardian. The adapter accepts anything with kickoff_async(inputs) (preferred) or kickoff(inputs) (sync; the adapter offloads to a thread).
Source: src/agent_guardian/adapters/framework/crewai.py.

Prerequisites

  • AgentGuardian installed in the same Python environment as your CrewAI project — pip install agent-guardian.
  • CrewAI installed in your project’s environment (pip install crewai).
  • A module-level Crew instance reachable on PYTHONPATH.
  • A model spec — --model stub for an offline dry-run, or a real model spec (openai:gpt-4o, gemini:gemini-2.5-flash) for a graded assessment.

Run target

Save the following as my_crew.py somewhere on your PYTHONPATH:
my_crew.py
The task description must reference {input} (a Jinja-style placeholder) — that’s the key the adapter maps the adversarial prompt onto. If your tasks expect different inputs keys, write a thin wrapper crew whose Task.description uses {input} and routes from there.

Run AgentGuardian

Point --framework-ref at MODULE:ATTR:
Flag-by-flag, every option below is verified against src/agent_guardian/cli.py:
  • --framework crewai — one of adk, autogen, crewai, langgraph, openai_agents, strands.
  • --framework-ref my_crew:research_crewMODULE:ATTR (colon form preferred; dotted form also accepted). The attribute must resolve to a Crew instance.
  • --model stub — offline default. Swap for a real model spec for a graded run.
  • --mode fast — caps each agent at 3 probes / 4 turns (~45s, ~$0.008 on Gemini). --mode smart / --mode full (default) for deeper runs.
  • --output md --output-path scan.md — Markdown report. Other formats: json, sarif, junit, pdf.
For CI gating against a real model with SARIF output:

Expected output

The scan emits the standard AgentGuardian report. The target block reflects the framework path:
is_multi_agent: true confirms that probes like memory poisoning across agents and inter-agent collusion are eligible to run. A finding under probe: "prompt_injection.*" against a CrewAI target usually means one crew member capitulated — trace evidence.transcript to identify which Agent.role produced the leak.

Common errors

  • CrewAIAdapter expected a Crew with .kickoff_async() or .kickoff(). The attribute you pointed --framework-ref at is not a CrewAI Crew instance (or duck-typed equivalent). Double-check the ref resolves to the Crew object, not the module or a sub-task.
  • CrewAIAdapter: crew returned None. The crew’s kickoff returned None for an adversarial prompt — usually a CrewAI configuration issue (no agents, no tasks, or Process.hierarchical without a manager). Verify the crew runs end-to-end on a benign prompt first.
  • Task description doesn’t substitute {input}. Your Task.description is a literal string. Use {input} (or a CrewAI template variable) so the adapter’s prompt actually reaches the crew.
  • tier = T4 against a tool-bearing crew. Force the tier explicitly with --tier T1 when your crew binds tools or per-agent memory; the framework adapter doesn’t introspect tool bindings.

Next step

  • Compare against the framework that gives the swarm step-level visibility: Scan a LangGraph agent.
  • For an MCP-server-backed tool surface used by your crew, read Scan an MCP server.
  • For CI gating, wire the same scan into GitHub Actions with --fail-under 70 and --output sarif.