Skip to content

Repository files navigation

graph-density-engine

A pure-Python, zero-dependency framework for testing how communication topology affects multi-agent communication systems — Erdős–Rényi graph generation, deterministic agent policies, and reproducible density sweeps in one pipeline.

Python Version License

Most multi-agent tutorials pick a communication topology by instinct — a fully connected mesh because it "feels safer," or a chain because it's easy to trace. This library isolates relationship density as a single, controlled variable, so you can measure whether adding communication pathways actually changes what a network can do, instead of assuming it does.

Read the full write-up on Towards Data Science → Graph Engineering Isn't About More Connections — It's About Which Ones Get Used

What It Does

Topology Generator → Router → Agent Policy → Shared State → Telemetry → Diagnostic Metrics
   (Erdos-Renyi,      (picks    (PureAgent:
    density-locked)    next      novelty-seeking,
                       speaker)  then repeat)

Five components, one Engine.run() call:

Component Job
Topology Generator Connected Erdős–Rényi random graphs at a locked target density, rejecting disconnected samples
Router Picks the next speaker from the current node's open outbound edges
Agent Policy Deterministic greedy-novelty-then-repeat policy (PureAgent), or a trivial DummyAgent for infrastructure validation
Telemetry Per-message logging feeding six diagnostic metrics
Diagnostic Metrics Relationship Efficiency, TF-IDF Redundancy, Information Gain, Edge Utilization, Communication Depth, and outcome metrics (Task Success, Information Recovery)

Installation

git clone https://github.com/Emmimal/graph-density-engine.git
cd graph-density-engine
pip install -r requirements.txt   # pytest only — for running the test suite

No other dependencies, at any stage. The graph engine, agent policy, and every metric (including a from-scratch TF-IDF implementation) run on the Python standard library alone. There is no API key, no network call, and no model of any kind anywhere in the pipeline.

Quick Start

from agents.policy import PureAgent
from datasets.loader import DatasetLoader
from graph.engine import Engine

loader = DatasetLoader()
scenario = loader.load("incident_01")
agent = PureAgent(scenario=scenario)

engine = Engine(communication_budget=35)
record = engine.run(agent, density_level=0.6, seed=42, scenario_id=scenario.scenario_id)

print(record.diagnostic_metrics["edge_utilization"])
print(record.diagnostic_metrics["tfidf_redundancy"])
print(record.final_facts)

Run this from the repository root — the package layout puts agents/, graph/, datasets/, and metrics/ directly at the top level, with no wrapping package directory.

Running the Experiment

Four phases, run in order, each validating the one before it:

Phase Command What It Shows
0 python -m pytest tests/ -v 16 unit tests validating every metric against synthetic examples, plus same-seed/different-seed reproducibility checks
1 python run_phase1.py Graph engine sanity check across the full density sweep, using a trivial DummyAgent — infrastructure only, no behavioral claim
2 python run_phase2.py --trials 10 --out results.json The real experiment: 50 runs (5 density levels × 10 trials) with the deterministic PureAgent

Note: Phase 2b requires run_experiment2.py, which isn't yet present in the repository's root file listing as of this writing. Push it before publishing this table, or remove the row until it is.

Configuration Reference

Engine(
    num_agents=8,                  # Fixed agent count
    communication_budget=35,       # Max messages per trial before a forced timeout
    router=None,                   # Defaults to uniform-random edge selection
)

engine.run(
    agent,                         # DummyAgent or PureAgent — same interface, either works
    density_level=0.6,             # 0.0-1.0, fraction of the 56 possible directed edges (at 8 agents)
    seed=42,                       # Full reproducibility: same seed -> identical topology and trace
    scenario_id="incident_01",     # Which frozen dataset scenario to load
    synthesis_check=...,           # Optional early-exit predicate (default: run to full budget)
)

Density sweep used throughout the published results: [0.2, 0.4, 0.6, 0.8, 1.0], 10 trials each, seeds locked before execution.

Project Structure

graph-density-engine/
├── state.py, context.py, agent_output.py       # Core dataclasses
├── agents/
│   ├── __init__.py
│   ├── base.py                                 # Agent interface/base class
│   ├── dummy.py                                # Trivial agent for infrastructure validation
│   └── policy.py                               # PureAgent — deterministic novelty-seeking policy
├── graph/
│   ├── __init__.py
│   ├── budget.py                                # Message-budget tracking
│   ├── topology.py                              # Connected Erdos-Renyi generator
│   ├── router.py                                # Edge selection
│   ├── telemetry.py                             # Per-trial recording
│   └── engine.py                                # Orchestrates one trial end to end
├── metrics/
│   ├── __init__.py
│   ├── base.py                                  # Shared metric interface
│   ├── tfidf.py                                 # From-scratch TF-IDF vectorizer + cosine similarity
│   ├── tfidf_redundancy.py
│   ├── relationship_efficiency.py
│   ├── information_gain.py
│   ├── edge_utilization.py
│   ├── communication_depth.py
│   ├── state_size.py
│   └── outcome/
│       ├── __init__.py
│       ├── information_recovery.py
│       ├── task_success.py
│       ├── latency.py
│       └── token_cost.py
├── datasets/
│   ├── __init__.py
│   ├── generate_datasets.py                     # Builds the frozen incident_01..10.json corpus
│   ├── loader.py
│   └── incident_01.json … incident_10.json
├── tests/                                       # 6 files, 16 tests — Phase 0 + reproducibility suite
│   ├── __init__.py
│   ├── test_topology.py
│   ├── test_edge_utilization.py
│   ├── test_information_gain.py
│   ├── test_relationship_efficiency.py
│   ├── test_tfidf_redundancy.py
│   └── test_reproducibility.py
├── run_phase1.py, run_phase2.py
├── phase2_results.json
├── experiment.md                                # Frozen pre-registration protocol
├── interfaces.md                                # Frozen interface contracts
├── README.md
└── requirements.txt

Performance (CPU only, zero API calls)

Operation Measured Time
Phase 0 — 16 unit tests under 0.25s
Phase 1 — 50 runs, DummyAgent under 1s
Phase 2 — 50 runs, PureAgent near-instant (not separately benchmarked)
API cost, any phase $0

Phase 0 and Phase 1 timings above are measured on this machine; Phase 2 has not been separately benchmarked, and multi-machine/multi-OS reproducibility has not been independently verified. What's confirmed: the graph engine and agent policy are fully deterministic given a fixed seed (see tests/test_reproducibility.py), and every trial in the published sweep completed without a timeout.

When to Use This

Worth adapting if you:

  • Are choosing a multi-agent communication topology by instinct rather than measurement
  • Want a template for running controlled, reproducible agent-architecture experiments without spending API budget on every iteration

Skip it if you:

  • Want a specific density value to copy into production — these numbers are scoped to one task, one topology family, one agent count
  • Have a bottleneck in individual agent reasoning quality rather than communication structure
  • Need true model stochasticity — this framework deliberately trades that away for exact reproducibility

Known Limitations

  • The agent policy is deterministic and rule-based, not an LLM. Results describe how a fixed, rational communication strategy behaves under different topologies, not how a stochastic model population would.
  • Information Recovery uses keyword-overlap matching, not semantic similarity — a documented, deliberate trade-off for staying dependency-free.
  • The included dataset corpus rotates 3 incident templates across 10 scenario files.
  • The default 35-message communication budget is generous relative to the included 17-fact scenarios, producing a ceiling effect — see experiment.md §12 for the full amendment history, including a bug that was found and fixed in the Information Recovery threshold and in an earlier circular stopping condition.

About

A pure-Python, zero-dependency framework for testing how communication topology affects multi-agent communication systems — Erdős–Rényi graph generation, deterministic agent policies, and reproducible density sweeps in one pipeline.

About

A pure-Python, zero-dependency framework for testing how communication topology affects multi-agent LLM systems — Erdős–Rényi graph generation, deterministic agent policies, and reproducible density sweeps in one pipeline.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages