CrewAI
Wrap a CrewAI Crew so its tool calls route through ArmorIQ
CrewAI Integration
ArmorIQCrew wraps CrewAI's Crew. On kickoff() it derives a plan from the
crew's tools and tasks, mints one intent token for the run, and patches each
ArmorIQ-backed tool so its execution routes through the ArmorIQ proxy instead
of calling out directly.
Live in Python only. Ships in armoriq-sdk. There is no TypeScript
CrewAI adapter. See Integrations for the status matrix.
This is a narrower adapter than Google ADK, LangChain or Strands. It gives you intent verification and audit, but not per-user scoping, per-call policy enforcement, holds, or approvals. Read Limitations before choosing it.
Install
pip install "armoriq-sdk[crewai]"Usage
from armoriq_sdk import ArmorIQClient
from armoriq_sdk.integrations.crewai import ArmorIQCrew
client = ArmorIQClient(api_key=os.environ["ARMORIQ_API_KEY"])
crew = ArmorIQCrew(
agents=[researcher, writer],
tasks=[research_task, write_task],
armoriq_client=client,
llm="gpt-4o",
)
result = crew.kickoff()Every argument other than armoriq_client, llm and token_validity_seconds
is forwarded to crewai.Crew, so an existing crew definition moves over
unchanged. kickoff_async() works the same way.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
armoriq_client | ArmorIQClient | required | Holds your API key and endpoints |
llm | str | required | LLM identifier recorded on the plan, e.g. "gpt-4o" |
token_validity_seconds | float | 3600.0 | Intent-token validity window for the run |
*args, **kwargs | Forwarded to crewai.Crew |
Which tools get protected
The adapter only wraps tools that expose both a .mcp and an .action
attribute. It walks every agent's tools list, deduplicates by object identity,
and patches _run on each match.
A standard crewai tool does not have those attributes, so it is not
wrapped and executes exactly as it would without ArmorIQ. Your ArmorIQ-backed
tools need to carry the MCP name and action they map to.
The generated plan has one step per unique (mcp, action) pair, with the goal
derived from your tasks' description (falling back to expected_output).
Steps carry no parameters, so verification is at the action level rather than
the argument level.
It fails open when it finds nothing to protect. If no tool on any agent
has .mcp and .action, the adapter logs
No ArmorIQ tools found; crew runs without ArmorIQ verificationat WARNING level, mints no token, and runs the crew anyway. A misconfigured tool therefore looks like a successful protected run unless you are watching the logs. Assert on your logging, or check that the tools you expect to be wrapped really do carry both attributes.
Limitations
| Google ADK / LangChain / Strands | CrewAI | |
|---|---|---|
| Intent token minted from the plan | Yes | Yes |
| Tool calls routed through the proxy | Yes | Yes |
Per-user scoping (for_user(email)) | Yes | No - the whole crew runs as one identity |
| Per-call policy enforcement (allow / hold / block) | Yes | No |
| Holds and approval waiting | Yes | No |
| Live enforcement events | Strands, LangChain | No |
| Plan step granularity | per tool call, with args | per (mcp, action), no args |
Practical consequences:
- Audit records are attributed to the client's base identity, not to an end user. If you serve multiple users, their activity is not distinguishable.
- Policies that depend on the acting user, or that hold a call for approval, will not be evaluated on this path.
- One token covers the whole
kickoff(), so its validity has to span the entire crew run. That is why the default is an hour rather than the SDK's usual 60 seconds.
If you need any of the above on CrewAI, skip the adapter and call
ArmorIQClient from inside your BaseTool._run instead. That gives you the
full session surface at the cost of about ten lines per tool. See
Custom frameworks.