Sandbox your CrewAI agents with IronClaw¶
You built a crew with CrewAI: several agents, each with a role and tools, handing work to one another. Multi-agent is where the blast radius grows. Every agent in the crew runs in your process with your keys, every tool runs with your privileges, and agents talk to each other in-process with no boundary between them. A single poisoned task can travel the whole crew.
IronClaw runs the same crew behind sealed, per-session sandboxes: no network card, model keys held host-side, agent-to-agent messaging host-mediated and audited (agents never talk peer-to-peer), and spawning a new agent gated on mandatory human approval because a new agent is a new trust principal.
Runnable example
A one-command CrewAI-to-IronClaw example lives at
examples/integrations/crewai:
a crew whose tool and code execution is backed by IronClaw sandboxes, with a
blocked escape attempt printed at the end. It ships with the integration
examples. The credential-free demo below runs the same sealed loop today.
The three-line fix¶
Stop running crew members in your own process. Declare each one to IronClaw and it runs inside its own sealed, network-free sandbox, with hand-offs host-mediated:
export OPENAI_API_KEY=sk-... # host-side only; no sandbox ever sees this key
./bin/controlplane --dev --api-addr 127.0.0.1:8787 &
ironctl agent create --name "Researcher" --provider openai --model gpt-4o \
--instructions "Research the topic and cite sources." --tool web_search --tool http_fetch --yes
Repeat one ironctl agent create per crew member. Same roles, same tools, now with
a boundary at every hand-off and every spawn. Full mapping below.
IronClaw does not run your Python in the sandbox, and that is the point
IronClaw's sandbox has no interpreter and no in-sandbox install. You do not wrap the CrewAI process; you re-declare each crew member (role, model, tools) as an IronClaw agent group, and IronClaw runs them inside the sealed runtime. See Skills and Security and isolation.
Why sandbox this¶
A typical CrewAI crew:
from crewai import Agent, Crew, Task
researcher = Agent(role="Researcher", tools=[search_tool], llm=llm) # key in-process
writer = Agent(role="Writer", tools=[file_tool], llm=llm)
crew = Crew(agents=[researcher, writer], tasks=[Task(...)])
crew.kickoff() # agents run in-process, hand off in-process, tools run on your box
The multi-agent shape multiplies the exposure:
- Every agent holds the keys. More agents, more places
sk-...lives. - Tools run with your privileges.
search_tool,file_tool, and any shell or HTTP tool execute on your host. Any crew member is a path in. - Hand-offs have no boundary. Agents pass work in-process; a compromised researcher can steer the writer with no gate between them.
IronClaw puts a boundary at each of those seams.
See it work first (no credentials)¶
Watch the sealed loop run with the offline mock provider, no key required:
git clone https://github.com/IronSecCo/ironclaw.git && cd ironclaw
docker compose -f docker-compose.demo.yml up --build -d # start the demo control-plane
curl -s -X POST http://127.0.0.1:8787/v1/ui/chat/send \
-H 'authorization: Bearer ironclaw-demo' -H 'content-type: application/json' \
-d '{"agentGroupID":"mock-agent","text":"hello from the crew"}'
sleep 3
curl -s -H 'authorization: Bearer ironclaw-demo' \
http://127.0.0.1:8787/v1/ui/chat/mock-agent/messages # the reply
The reply comes back through a real per-session sandbox and encrypted queues. Tear
down with docker compose -f docker-compose.demo.yml down. For a two-agent shape
close to a crew, see
examples/multi-agent-team.
Port your crew¶
Each CrewAI Agent becomes an IronClaw agent group:
| CrewAI | IronClaw | Notes |
|---|---|---|
Agent(role=..., llm=...) |
one ironctl agent create per member |
Each crew member is its own sandboxed agent group. |
llm=ChatOpenAI(api_key=...) |
--provider openai + host OPENAI_API_KEY |
Keys are host-side and injected by the model-proxy. No sandbox ever holds one. |
role / backstory / goal |
--identity / --soul / --instructions |
The agent's identity, voice, and operating rules. |
tools=[...] |
--tool <name> (built-in) or MCP |
Built-ins: read_file, write_file, list_dir, web_search, http_fetch. Custom tools attach over MCP. |
| Agent-to-agent hand-off | host-mediated a2a messaging | The control-plane routes and audits every hand-off; agents never talk peer-to-peer. |
Crew spawning an agent |
create_agent behind the approval gateway |
Spawning a new agent is never auto-approved (threat-model boundary B3). |
A researcher-plus-writer crew becomes two declared agents:
export OPENAI_API_KEY=sk-... # host-side only; no sandbox sees it
export IRONCLAW_API_TOKEN=$(openssl rand -hex 32)
./bin/controlplane --dev --api-addr 127.0.0.1:8787 &
ironctl agent create --name "Researcher" \
--provider openai --model gpt-4o \
--instructions "You research the topic and cite sources." \
--tool web_search --tool http_fetch --yes
ironctl agent create --name "Writer" \
--provider openai --model gpt-4o \
--instructions "You turn research notes into a short report." \
--tool read_file --tool write_file --yes
The multi-agent-team
example wires two agents into one shared channel with priority and engage rules,
so you can see mediated hand-off end to end.
What you gained¶
- Keys left every agent. Injected host-side per request; no crew member holds a secret to leak.
network=noneby default. Each agent runs with no NIC; egress is the audited model-proxy socket plus explicitly allowlisted hosts.- Hand-offs and spawns are gated. Agent-to-agent messages are host-routed and
audited, and
create_agentalways requires human approval. See the threat model (boundary B3).
The crew you designed in CrewAI, with a boundary at every seam it did not have.