Independent#
Several copies of one agent answer the same input in parallel and never see each other's work. A majority vote then picks one answer. It measures what an ensemble adds without any communication.
How it works#
- The runner reads one seed prompt for the dataset and gives it, unchanged, to every replica.
- A LangGraph
StateGraphfans out fromSTART: a conditional edge returns oneSendper replica (agent_0toagent_3). Each node runs a ReAct agent built withcreate_react_agentand the dataset's tools. - Replica
isends its requests with seedi; otherwise the replicas are identical. - All nodes edge to
END. Their answers are merged into one list by anoperator.addreducer. No replica reads another's output at any point. - The runner submits the majority answer, without looking at the gold answer or the tests:
| Datasets | Vote over |
|---|---|
| GPQA | extracted letters |
| HotpotQA | normalized short-form answers |
| MATH | buckets of \boxed{} answers that is_equiv treats as equal |
| BFCL | canonical function-call lists |
| LiveCodeBench, APPS | programs, compared with whitespace normalized; only the winner is tested |
| SWE-bench | non-empty patches, compared with whitespace normalized; only the winner is evaluated |
| ToolHop, API-Bank | final answers or API calls |
The largest bucket wins, ties go to the bucket with the lowest replica, and replicas without an answer abstain. The shared rule is in core/voting.py.
The replica count comes from the team spec (4) and INDEPENDENT_N_AGENTS overrides it. The ToolHop and API-Bank runners read TOOLHOP_INDEPENDENT_N_AGENTS or APIBANK_INDEPENDENT_N_AGENTS first. For the 2, 8 and 10 replica variants, see Team Sizes.
Agent role and seed prompt#
One role per dataset, shared by all replicas:
| Role | Datasets | Seed prompt |
|---|---|---|
solver |
gpqa, hotpotqa, math, toolhop, apibank |
configs/prompts/independent/<dataset>/solver.txt |
coder |
lcb, apps |
configs/prompts/independent/<dataset>/coder.txt |
caller |
bfcl |
configs/prompts/independent/bfcl/caller.txt |
patcher |
swe |
configs/prompts/independent/swe/patcher.txt |
Because every replica reads the same file, optimizing this topology means tuning one prompt that all four agents then use.
Implementation#
- Reference scaffold:
topologies/independent/langgraph_base.pyshows theSendfan-out and fan-in with four agents. Its demo agents have different personas; the benchmark runners use one shared prompt instead. - Dataset runners:
topologies/independent/<dataset>/langgraph_<dataset>.py. The GPQA, HotpotQA and MATH runners cap each row at 120 s of wall-clock time and the LiveCodeBench and APPS runners at 180 s, so one stuck replica can't stall a batch. On SWE-bench, each replica edits its own clone of the repository. - ToolHop and API-Bank: no LangGraph graph. The runner calls the shared tool loop (ToolHop) or model call (API-Bank) once per seed in plain Python and votes over the results.
Run it#
python -m topologies.independent.hotpotqa.langgraph_hotpotqa
python -m topologies.independent.hotpotqa.langgraph_hotpotqa --batch --limit 100 \
--out-dir results/topologies_baseline/independent_hotpotqa
export TOOLHOP_ALLOW_DATASET_EXEC=1
INDEPENDENT_N_AGENTS=8 python -m topologies.independent.toolhop.langgraph_toolhop \
--limit 100 --out-dir results/topologies_baseline/independent_toolhop_n8
See the task pages for each dataset's options.
Optimize it#
The protocol topology is independent; add --team-size or --communication for the team-size and communication-protocol variants. The optimizer tunes the one shared prompt. Any of the eight methods runs it; for example, MAMUT-GEPA on HotpotQA:
python -m optimizers.protocol.run --method mamut_gepa --dataset hotpotqa --topology independent \
--model qwen --seed 0 --out runs/mamut_gepa/hotpotqa/independent/qwen/0
See Run an Optimizer.