Inspect Swarm runs a swarm of agents on one sample of an Inspect task. A swarm is an Inspect agent, so it replaces the task’s solver, and the task’s scorer scores the swarm’s answer the same way it would score a single agent. Everything in the package is experimental and may change in any release. We’re sharing it now because the question it is built to ask, whether a team of agents beats one agent at the same budget and by how much, is one that several groups are already answering with harnesses of their own.
Pass swarm() as the solver of an existing task:
from inspect_ai import eval
from inspect_ai.agent import react
from inspect_swarm import member, swarm
from my_tasks import my_task
eval(
my_task(),
solver=swarm(members=member(react, count=4)),
model="anthropic/claude-sonnet-4-5",
)Each sample runs four react() members at the same time. Each starts with the sample’s input and a short preamble: its name, the number of members, and how to share files. The swarm stops at the first submission and uses it as its answer. The other members finish the calls they have in flight and stop.
A task can also build the swarm itself, which makes the number of members a task parameter:
@task
def getting_started(k: int = 3) -> Task:
return Task(
dataset=QUESTIONS,
solver=swarm(members=member(react, count=k), channels=[]),
scorer=match(),
token_limit=200_000,
)-T k=1 is a swarm of one: a single agent run under the swarm’s rules with the same records, which is the arm to compare against.
Members, Controllers, Channels, and Budgets
A swarm is composed from four pieces, each of which can be changed on its own:
- Members are agents registered with
@agent, such asreact()ordeepagent(). Give a factory and a count, or an agent you have built. Members can have roles, their own models, and their own limits. - Controllers decide which members start, when, and when the swarm is done. The built-in
leaderlesscontroller starts every member and stops at the first submission. A controller of your own is a short async function: start one member and escalate to the rest only if it gives up, or hand tasks in turn to a persistent worker that keeps its context between activations. - Channels decide how members share information. The default
filesystemchannel states a convention for sharing files in the sandbox.shared_memorygives members a board of files with a record of every write and read, andmessagesgives them direct messages. - Budgets cap cost, tokens, and time. By default the swarm derives its caps from the sample’s limits and members share them as a pool.
split="equal"gives each member a fixed share instead, so the split stays a condition of the experiment.
What the Log Records
Each member’s events are in a timeline named after it, so Inspect View shows one member’s trajectory at a time. When the swarm ends it writes a result record to the transcript with each member’s state and status and which member’s output is the answer. It also writes a ledger of the caps and each member’s usage and cost, and metrics covering tokens, time, how members acted and communicated, and the critical path: the number of model calls the answer depended on, one after another, across members. These appear as columns in samples_df() for analysis.
Sweeps
Agent count, budget, and split are task parameters, so they sweep like anything else:
inspect eval examples/budget_sweep.py -T k=8 -T budget=8 -T split=equalHold the budget fixed and vary k. Or fix a per-agent budget b, run budget = k * b with an equal split, and vary both. Or hold k and the budget and vary the split as an ablation. Compare arms on the cost the log records rather than on the caps.
Inspect Swarm currently depends on the main branch of inspect_ai, so installing it replaces a released inspect_ai in that environment. The documentation has runnable examples for each of the pieces above, and the designs behind the package are in the repository’s design directory.