Virtual Agent Economies¶
Components inspired by the "Virtual Agent Economies" paper (Tomasev et al., arXiv 2509.10147), implementing concepts from the paper that extend the simulation framework with fair allocation, collective coordination, high-frequency dynamics, boundary permeability, and identity infrastructure.
Table of Contents¶
- Dworkin-Style Auctions
- Mission Economies
- High-Frequency Negotiation
- Permeability Model
- Identity and Trust Infrastructure
- Further Reading
Dworkin-Style Auctions¶
Fair resource allocation using auction mechanisms inspired by Ronald Dworkin's approach to distributive justice. Agents start with equal token endowments and bid on resource bundles. The mechanism uses tatonnement (iterative price adjustment) to find market-clearing prices, then verifies envy-freeness.
Source: src/env/auction.py
How It Works¶
- All agents receive equal token endowments
- Agents submit bids expressing resource valuations
- Tatonnement adjusts prices proportional to excess demand until convergence
- Allocations are normalized so demand does not exceed supply
- Envy-freeness is verified: no agent prefers another's bundle at clearing prices
Quick Start¶
from src.env.auction import DworkinAuction, AuctionConfig, AuctionBid
# Configure the auction
config = AuctionConfig(
initial_endowment=100.0,
max_rounds=50,
price_adjustment_rate=0.1,
convergence_tolerance=0.01,
envy_tolerance=0.05,
)
auction = DworkinAuction(config)
# Define agent bids
bids = {
"agent_1": AuctionBid(
agent_id="agent_1",
valuations={"compute": 2.0, "data": 1.0, "bandwidth": 0.5},
budget=100.0,
),
"agent_2": AuctionBid(
agent_id="agent_2",
valuations={"compute": 0.5, "data": 2.0, "bandwidth": 1.5},
budget=100.0,
),
}
# Available resources
resources = {"compute": 10.0, "data": 20.0, "bandwidth": 15.0}
# Run the auction
result = auction.run_auction(bids, resources)
print(f"Converged: {result.converged} in {result.rounds_to_converge} rounds")
print(f"Envy-free: {result.is_envy_free}")
print(f"Total utility: {result.total_utility:.2f}")
# Check allocation fairness
gini = auction.compute_gini_coefficient(result.allocations)
print(f"Utility Gini: {gini:.3f}") # 0 = perfect equality
Configuration¶
| Parameter | Default | Description |
|---|---|---|
initial_endowment |
100.0 | Equal token budget per agent |
max_rounds |
50 | Maximum tatonnement iterations |
price_adjustment_rate |
0.1 | Price change speed (0, 1] |
convergence_tolerance |
0.01 | Max excess demand for convergence |
envy_tolerance |
0.05 | Utility gap tolerance for envy-freeness |
Connection to Soft Labels¶
Agent effective endowments can be modulated by reputation (derived from average p history), linking allocation fairness to the quality signal pipeline.
Mission Economies¶
Collective goal coordination where agents align around shared societal missions with measurable criteria. Contributions are evaluated using the soft-label quality pipeline, and rewards are distributed proportional to individual contributions.
Source: src/env/mission.py
How It Works¶
- An agent proposes a mission with objectives, reward pool, and deadline
- Other agents join the mission
- Agents contribute interactions toward mission objectives
- At deadline (or when objectives are met), the mission is evaluated
- Rewards are distributed based on the configured strategy
Quick Start¶
from src.env.mission import MissionEconomy, MissionConfig, MissionObjective
config = MissionConfig(
enabled=True,
min_participants=2,
max_active_missions=5,
reward_distribution="proportional", # "equal", "proportional", or "shapley"
)
economy = MissionEconomy(config)
# Propose a mission
objectives = [
MissionObjective(
description="Maintain high quality interactions",
target_metric="avg_p",
target_value=0.7,
weight=1.0,
),
MissionObjective(
description="Reach interaction volume target",
target_metric="total_count",
target_value=50.0,
weight=0.5,
),
]
mission = economy.propose_mission(
coordinator_id="agent_1",
name="Quality Improvement Initiative",
objectives=objectives,
reward_pool=100.0,
deadline_epoch=20,
current_epoch=0,
)
# Other agents join
economy.join_mission("agent_2", mission.mission_id)
economy.join_mission("agent_3", mission.mission_id)
# Record contributions (interactions submitted toward mission goals)
economy.record_contribution("agent_1", mission.mission_id, interaction)
# Evaluate mission
result = economy.evaluate_mission(mission.mission_id, all_interactions, current_epoch=20)
print(f"Score: {result['mission_score']:.2f}, Status: {result['status']}")
# Distribute rewards
rewards = economy.distribute_rewards(mission.mission_id, all_interactions)
for agent_id, amount in rewards.items():
print(f" {agent_id}: {amount:.2f}")
# Check for free-riding
gini = economy.free_rider_index(mission.mission_id)
print(f"Free-rider index (Gini): {gini:.3f}")
Reward Distribution Strategies¶
| Strategy | Description |
|---|---|
| equal | Equal split among all contributors |
| proportional | Weighted by contribution count and average p (quality-weighted) |
| shapley | Approximate Shapley values based on marginal quality improvement + volume share |
Supported Objective Metrics¶
| Metric | Description |
|---|---|
avg_p |
Average p across contributed interactions |
min_p |
Minimum p (worst-case quality) |
total_count |
Number of contributed interactions |
acceptance_rate |
Fraction of interactions that were accepted |
total_welfare |
Sum of expected surplus: p * 2.0 - (1-p) * 1.0 |
High-Frequency Negotiation¶
Models speed-based market dynamics where agents submit orders at high rates, with risk of flash crashes (sudden correlated quality collapses). Includes a flash crash detector and circuit breaker mechanism.
Source: src/env/hfn.py
How It Works¶
- Agents submit bid/ask/cancel orders to an order book
- Orders are sorted by price priority and effective arrival time (including latency noise)
- At batch intervals, matching bids and asks are cleared at midpoint price
- A flash crash detector monitors price drops within a rolling window
- Circuit breaker halts the market if a crash is detected
Quick Start¶
from src.env.hfn import HFNEngine, HFNConfig, HFNOrder
config = HFNConfig(
tick_duration_ms=100.0,
max_orders_per_tick=10,
latency_noise_ms=10.0,
batch_interval_ticks=5,
halt_duration_ticks=20,
)
engine = HFNEngine(config, seed=42)
# Submit orders
engine.submit_order(HFNOrder(
agent_id="agent_1",
order_type="bid",
resource_type="compute",
quantity=5.0,
price=1.2,
))
engine.submit_order(HFNOrder(
agent_id="agent_2",
order_type="ask",
resource_type="compute",
quantity=5.0,
price=1.1,
))
# Process a tick (matches orders at batch intervals)
tick = engine.process_tick()
print(f"Tick {tick.tick_number}: price={tick.market_price:.2f}, "
f"spread={tick.bid_ask_spread:.2f}, halted={tick.halted}")
# Check for flash crashes
crashes = engine.get_crash_history()
for crash in crashes:
print(f"Flash crash at tick {crash.start_tick}: "
f"drop={crash.price_drop_pct:.1%}, severity={crash.severity:.2f}")
# Fairness metric
gini = engine.speed_advantage_gini()
print(f"Speed advantage Gini: {gini:.3f}")
Flash Crash Detection¶
The FlashCrashDetector monitors price changes within a rolling window:
| Parameter | Default | Description |
|---|---|---|
price_drop_threshold |
0.1 | Fractional drop to trigger (10%) |
window_ticks |
10 | Rolling window size |
volume_spike_factor |
3.0 | Volume multiplier for detection |
When a crash is detected, the market halts via circuit breaker for halt_duration_ticks.
HFN Configuration¶
| Parameter | Default | Description |
|---|---|---|
tick_duration_ms |
100.0 | Duration of one tick |
max_orders_per_tick |
10 | Per-agent rate limit |
latency_noise_ms |
10.0 | Random latency added to orders |
priority_by_speed |
True | Faster orders get priority |
batch_interval_ticks |
5 | Ticks between batch clearing |
halt_duration_ticks |
20 | Market halt duration after crash |
Connection to Soft Labels¶
Every executed trade generates an interaction with associated p values. Flash crashes manifest as sudden drops in the average p of accepted interactions.
Permeability Model¶
Models sandbox boundaries as semi-permeable membranes with parameterized permeability (0 = fully sealed, 1 = fully open). Includes contagion modeling for how harmful interactions inside the sandbox propagate to the external world.
Source: src/boundaries/permeability.py
How It Works¶
- Effective permeability is computed from base level, threat, and agent trust
- Individual flows are probabilistically allowed or blocked based on permeability and interaction quality
- Contagion probability links harm level to boundary crossing:
prob = contagion_rate * (1-p) * permeability - Spillover events track harm that escapes the sandbox, with external amplification
Quick Start¶
from src.boundaries.permeability import PermeabilityModel, PermeabilityConfig
config = PermeabilityConfig(
base_permeability=0.5,
contagion_rate=0.05,
spillover_amplification=1.5,
adaptive=True,
threat_sensitivity=1.0,
)
model = PermeabilityModel(config, seed=42)
# Compute effective permeability under threat
perm = model.compute_effective_permeability(
threat_level=0.3,
agent_trust=0.8,
)
print(f"Effective permeability: {perm:.3f}")
# Simulate spillover from a batch of interactions
spillovers = model.simulate_spillover(interactions)
print(f"Spillovers: {len(spillovers)}, "
f"blocked: {sum(1 for s in spillovers if s.blocked)}")
# Metrics
print(f"Containment rate: {model.containment_rate():.1%}")
print(f"Cumulative external harm: {model.state.cumulative_external_harm:.2f}")
# Find optimal permeability
optimal = model.optimal_permeability(
interactions,
external_harm_weight=1.0,
n_samples=10,
)
print(f"Optimal permeability: {optimal:.2f}")
Adaptive Permeability¶
When adaptive=True, effective permeability adjusts dynamically:
Where:
- threat_factor = 1.0 - (threat_level * threat_sensitivity), clamped to [0, 1]
- trust_factor = 0.5 + 0.5 * agent_trust
Higher threat tightens the boundary; higher trust loosens it.
Configuration¶
| Parameter | Default | Description |
|---|---|---|
base_permeability |
0.5 | Base permeability [0, 1] |
information_decay |
0.1 | Quality degradation on crossing |
contagion_rate |
0.05 | Base contagion probability |
spillover_amplification |
1.5 | Harm amplification factor |
adaptive |
True | Enable adaptive permeability |
threat_sensitivity |
1.0 | How strongly threat reduces permeability |
Connection to Soft Labels¶
Contagion probability is directly proportional to (1-p) * permeability, linking boundary dynamics to the quality signal pipeline. Low-quality interactions (low p) are more likely to cause spillover harm.
Identity and Trust Infrastructure¶
Implements verifiable credentials, Proof-of-Personhood, and Sybil detection for the simulation. These are abstracted versions of the cryptographic infrastructure proposed in the paper.
Source: src/models/identity.py, src/governance/identity_lever.py
Components¶
| Component | Description |
|---|---|
VerifiableCredential |
Unforgeable claims with expiry and revocation |
AgentIdentity |
Extended identity with credentials and trust score |
CredentialIssuer |
System-level credential issuance and verification |
IdentityRegistry |
Identity management and Sybil detection |
SybilDetectionLever |
Governance lever for Sybil penalties |
Quick Start¶
from src.models.identity import (
IdentityRegistry, IdentityConfig, CredentialIssuer,
)
# Configure identity infrastructure
config = IdentityConfig(
identity_creation_cost=10.0,
proof_of_personhood_required=False,
credential_expiry_epochs=50,
sybil_detection_enabled=True,
max_identities_per_entity=1,
behavioral_similarity_threshold=0.8,
)
registry = IdentityRegistry(config)
# Create identities
identity = registry.create_identity(
"agent_1",
entity_id="entity_a",
proof_of_personhood=True,
current_epoch=0,
)
print(f"Trust score: {identity.trust_score:.2f}")
# Issue credentials
issuer = CredentialIssuer(config)
cred = issuer.issue_reputation_credential("agent_1", reputation=0.85, current_epoch=5)
identity.credentials.append(cred)
# Recompute trust
score = identity.compute_trust_score(current_epoch=5)
print(f"Updated trust: {score:.2f}")
# Detect Sybil clusters
patterns = {
"agent_1": {"target_a": 10, "target_b": 5},
"agent_2": {"target_a": 10, "target_b": 5}, # Suspiciously similar
"agent_3": {"target_c": 8, "target_d": 3}, # Different pattern
}
clusters = registry.detect_sybil_clusters(patterns)
print(f"Sybil clusters found: {len(clusters)}")
Trust Score Computation¶
Trust is built from credentials and Proof-of-Personhood:
| Component | Score |
|---|---|
| Base (new identity) | 0.3 |
| Proof-of-Personhood | +0.2 |
| Per valid credential | +0.1 (max 0.5 from credentials) |
| Maximum | 1.0 |
Sybil Detection¶
Behavioral similarity analysis identifies clusters of agents that appear to be controlled by the same entity. The algorithm computes a combined Jaccard + cosine similarity score from interaction patterns:
- Jaccard similarity of counterparty sets
- Cosine similarity of normalized interaction frequency vectors
- Combined score = average of the two
Agents above the behavioral_similarity_threshold are clustered together.
Sybil Detection Governance Lever¶
The SybilDetectionLever integrates with the governance engine:
from src.governance import GovernanceConfig
gov_config = GovernanceConfig(
sybil_detection_enabled=True,
sybil_similarity_threshold=0.8,
sybil_penalty_multiplier=1.0,
sybil_realtime_penalty=True,
sybil_realtime_rate=0.1,
sybil_max_cluster_size=3,
)
| Parameter | Default | Description |
|---|---|---|
sybil_detection_enabled |
False | Enable Sybil detection |
sybil_similarity_threshold |
0.8 | Behavioral similarity threshold |
sybil_penalty_multiplier |
1.0 | Penalty severity multiplier |
sybil_realtime_penalty |
False | Penalize flagged pairs on interaction |
sybil_realtime_rate |
0.1 | Per-interaction penalty amount |
sybil_max_cluster_size |
3 | Block agents in clusters larger than this |
Identity Event Types¶
| Event | Description |
|---|---|
IDENTITY_CREATED |
New agent identity registered |
CREDENTIAL_ISSUED |
Credential issued to an agent |
SYBIL_DETECTED |
Sybil cluster detected |
Further Reading¶
- Tomasev, N., Franklin, J., Leibo, J.Z., Jacobs, A.Z., Cunningham, T., Gabriel, I., & Osindero, S. (2025). Virtual Agent Economies: A Framework for Multi-Agent System Governance. arXiv:2509.10147. https://arxiv.org/abs/2509.10147
- Dworkin, R. (1981). What is Equality? Part 2: Equality of Resources. Philosophy & Public Affairs, 10(4), 283-345.
- Kyle, A.S., Obizhaeva, A.A., & Tuzun, T. (2017). Flash Crashes and Market Microstructure. Working Paper.
- Shapley, L.S. (1953). A Value for n-Person Games. Contributions to the Theory of Games, 2, 307-317.