> ## Documentation Index
> Fetch the complete documentation index at: https://docs.promptguard.co/llms.txt
> Use this file to discover all available pages before exploring further.

# CrewAI

> Scan a CrewAI crew’s inputs and result with kickoff callbacks, guard individual tools, and scan model calls with auto-instrumentation

```bash theme={"system"}
pip install "promptguard-sdk[crewai]"
```

## Kickoff callbacks

`PromptGuardGuardrail` gives you two callbacks for the crew's kickoff hooks: `before_kickoff` scans every non-empty string in the kickoff inputs, and `after_kickoff` scans the crew's result. Register them in CrewAI's `before_kickoff_callbacks` and `after_kickoff_callbacks` lists.

```python theme={"system"}
from crewai import Crew

from promptguard.integrations.crewai import PromptGuardGuardrail

pg = PromptGuardGuardrail()  # reads PROMPTGUARD_API_KEY

crew = Crew(
    agents=[researcher],
    tasks=[research_task],
    before_kickoff_callbacks=[pg.before_kickoff],
    after_kickoff_callbacks=[pg.after_kickoff],
)
crew.kickoff(inputs={"topic": user_topic})
```

<Warning>
  Pass them as the two `*_callbacks` lists. `Crew` has no `before_kickoff` or `after_kickoff` field, so `Crew(before_kickoff=pg.before_kickoff)`, the form in the SDK's docstring, registers nothing and nothing is scanned.
</Warning>

On a block, either callback raises `PromptGuardBlockedError` in enforce mode and the kickoff stops. On a redact decision, `before_kickoff` hands the crew the redacted inputs. `after_kickoff` cannot rewrite the crew's result, so in enforce mode a redact decision on the output blocks instead.

To scan one task's output, call `pg.scan_task_output(output, task_name="...")` yourself, for example from the task's own callback.

<Note>
  CrewAI 1.15 warns that bound-method callbacks such as `pg.before_kickoff` cannot be serialized and will prevent checkpointing. The warning does not stop them running. If you rely on checkpointing, scan the inputs before `crew.kickoff()` and the result after it with the [Guard client](/guides/python-sdk#guard-client) instead.
</Note>

## Guarding a tool

`secure_tool` wraps a tool class's `_run` so its input is scanned before the tool runs. A redact decision blocks in enforce mode, because the wrapper cannot rewrite the tool's arguments.

```python theme={"system"}
from crewai.tools import BaseTool

from promptguard.integrations.crewai import secure_tool


@secure_tool()  # reads PROMPTGUARD_API_KEY
class SearchTool(BaseTool):
    name: str = "search"
    description: str = "Search the web"

    def _run(self, query: str) -> str:
        return search(query)
```

## Auto-instrumentation

CrewAI calls OpenAI models through the `openai` package, so [auto-instrumentation](/integrations/auto-instrumentation) scans each agent's model calls as well. That scans every step the agents take, where the kickoff callbacks scan only what goes in and what comes out.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.