Sandboxes
Overview
A swarm has one of two sandbox topologies:
- Shared, the default: every member works in the sample’s sandbox, at the same time. Members can share files, and can change files under each other.
- Per member: each member works in a sandbox environment of its own, and members cannot reach each other’s. What they share goes through a channel, such as the shared-memory board, or a volume every member’s sandbox mounts.
Per member
With sandbox, a member works in a sandbox environment of its own, which becomes its default, so sandbox() in its tools returns it. {member} stands for the member’s name, so sandbox="{member}" gives each copy of a counted member its own:
from inspect_ai.agent import react
from inspect_ai.tool import bash
from inspect_swarm import member, swarm
solver = swarm(
members=member(
react, args={"tools": [bash()]}, name="agent", count=2, sandbox="{member}"
),
channels=[],
)agent-1 and agent-2 run in the environments of those names. With count=1 the member’s name has no number, so {member} is agent; a task whose member count is a parameter can give each member its own record, [member(..., name=f"agent-{i}", sandbox=f"agent-{i}") for i in range(1, k + 1)], so the names match the environments for every count. The sample’s sandbox configuration provides them (for Docker, a compose service for each), and the swarm checks that they exist when it starts:
services:
agent-1:
image: python:3.12-slim
command: tail -f /dev/null
network_mode: none
x-default: true
agent-2:
image: python:3.12-slim
command: tail -f /dev/null
network_mode: none- When one member has its own sandbox, every member must have one, and no two can have the same one.
- Tools that choose a sandbox without a name, such as bash(), text_editor(), bash_session() and the agent bridge, use the member’s own.
- The
filesystemchannel describes a shared sandbox, so it is refused: passchannels=[],channels=[shared_memory()]for a board the members share, orfilesystem(shared_volume=True)for a shared volume. - The preamble tells each member that it works in its own sandbox, which no other member can reach.
Sizing
The two topologies cost different resources:
- Shared: one sandbox runs every member’s tool calls at once. Size it for
kagents working at the same time, not one: CPU, memory, disk, and process limits. A compose service’scpusandmem_limitset them for Docker. - Per member: each sample starts
ksandboxes, plus any shared services. A sample of 32 members, each with a 32 GiB container, needs 32 such containers at once.
Inspect’s max_sandboxes (for Docker, twice the number of CPUs by default) limits how many samples have their sandboxes running at once, not how many containers they hold. With per-member sandboxes, the containers running at once can reach max_sandboxes × (k + services). Lower max_sandboxes or max_samples to fit the machine or cluster, and keep each member’s container no larger than one agent needs.
Scoring
The task’s scorer runs after the swarm, outside every member, where sandbox() is the sample’s default. A scorer that grades the members’ work names each member’s sandbox, as in sandbox("agent-1"). The result record’s sandbox field says which member used which. See Scoring.