The complete reference to trustlib-mas
A task-oriented guide to every class, method, parameter, and recipe in the library — for researchers, engineers, and students building trust-based decision logic into agents.
01Introduction
1.1 What This Guide Is
This is a practical, task-oriented guide to using
trustlib-mas in real applications. It complements the
mathematical details in the manuscript and the terse API summary in the
README. You do not need to read the manuscript to use this guide.
Version 1.1.0 of the library is aligned with v3 of the manuscript ("A Unified Dyadic and Collective Mathematical Framework") and adds a complete evaluation toolkit: ROC-AUC, precision–recall, repeated simulation with confidence intervals, ablation study, robustness checks, and a numeric verification of the Unification Theorem.
1.2 Who This Guide Is For
- Researchers building simulations of trust in multi-agent systems
- Engineers embedding trust-based decision logic into agents
- Students learning computational trust models
- Reviewers wanting to reproduce the manuscript's results
1.3 What You Can Build
- A buyer agent deciding whether to purchase from an unknown seller
- A passenger deciding whether to trust a robotaxi after a failure
- A logistics manager deciding whether to dispatch a truck platoon
- A patient evaluating a surgical team
- A DAO member evaluating a multi-signature wallet
- A user evaluating a hybrid human-AI fact-checking collective
1.4 Prerequisites
- Python 3.9 or later
- Basic familiarity with Python classes and functions
- No external libraries required
1.5 What's New in v1.1.0
| Feature | Status | Purpose |
|---|---|---|
verify_unification() | New | Numerically confirm all four parts of §3.8 |
roc_auc() | New | ROC-AUC via Mann–Whitney U |
precision_recall() | New | Precision & recall at a fixed threshold |
run_repeated_sim() | New | Repeated simulation with 95% CIs |
run_ablation_study() | New | Component-by-component ablation |
run_robustness_check() | New | Misspecification robustness |
HEURISTIC_NOTE | New | Documents κ as a heuristic |
__paper_version__ | New | Tracks the paper version ("v3") |
python -m trustlib_mas | New | CLI demo |
simulate_comparison() | Extended | Now returns ROC-AUC, precision, recall |
02Installation and Setup
2.1 Option A: PyPI Install
pip install trustlib-mas
from trustlib_mas import Trustee, Trustor, TrustScenario
2.2 Option B: Single-File Drop-In
Copy trustlib_mas.py into your project directory and import it directly:
my_project/
├── trustlib_mas.py
├── my_agent.py
└── ...
2.3 Option C: Source Install
git clone https://github.com/<your-username>/trustlib-mas.git
cd trustlib-mas
pip install -e .
2.4 Option D: Development Install
pip install -e ".[dev]"
2.5 Verifying Your Installation
import trustlib_mas
print(trustlib_mas.__version__) # "1.1.0"
print(trustlib_mas.__paper_version__) # "v3"
print(trustlib_mas.HEURISTIC_NOTE[:60] + "...")
Or run the built-in CLI demo:
python -m trustlib_mas
2.6 Importing What You Need
from trustlib_mas import (
# Core classes
Trustee, Trustor, TrustGroup, TrustScenario, TrustNetwork,
# Aggregation
AggregationType,
# Helper functions
harmonic_mean, geometric_mean, arithmetic_mean, median,
sigmoid, strategic_factor,
# Simulation and evaluation
simulate_comparison,
run_repeated_sim,
run_ablation_study,
run_robustness_check,
verify_unification,
# Classification metrics
roc_auc,
precision_recall,
# Constants
HEURISTIC_NOTE,
)
03Naming, Imports, and Versioning
3.1 Names at a Glance
| Artifact | Name |
|---|---|
| PyPI package | trustlib-mas |
| Python import | trustlib_mas |
| Repository | trustlib-mas |
| Main module file | trustlib_mas.py |
| Compatibility shim | trustlib.py |
| CLI entry point | python -m trustlib_mas |
3.2 Why the Hyphen–Underscore Split?
Python does not allow hyphens in module names, so the PyPI name
(trustlib-mas) uses a hyphen while the import name
(trustlib_mas) uses an underscore.
3.3 Version Tracking
import trustlib_mas
trustlib_mas.__version__ # "1.1.0"
trustlib_mas.__paper_version__ # "v3"
3.4 Backward Compatibility
from trustlib import Trustee, Trustor, TrustScenario # still works
3.5 Deprecation Timeline
| Version | Status |
|---|---|
1.0.x (trustlib) | Legacy. No longer maintained. |
1.1.x (trustlib-mas) | Current. Shim provided. |
2.0.x (planned) | Shim may be removed. |
04Conceptual Overview
4.1 The Trust Decision Problem
At its core, every use of trustlib-mas answers the question:
4.2 The Three-Box Mental Model
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ TRUSTEE(S) │ │ TRUSTOR │ │ SCENARIO │
│ Who is being │ │ Who is deciding │ │ What are the │
│ evaluated? │ │ whether to trust? │ │ payoffs and stakes?│
│ │ │ │ │ │
│ Trustee │ │ Trustor │ │ TrustScenario │
│ TrustGroup │ │ τ, ρ, δ*, β_s │ │ U_win, U_loss, S │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
4.3 The Seven Layers at a Glance
| Layer | What It Models | Where You Set It |
|---|---|---|
| L1 | Perceived ability, benevolence, integrity | Trustee.A, .B, .I |
| L2 | Risk-adjusted expected utility | TrustScenario.U_win, .U_loss, .stakes |
| L3 | Bayesian reliability with recency | Trustee.a, .b |
| L4 | Asymmetric trust build/destroy | Trustee.k_build, .k_destroy |
| L5 | Strategic cooperation threshold | Trustee.discount_factor, Trustor.delta_star |
| L6 | Network propagation | TrustNetwork |
| L7 | Group aggregation | TrustGroup |
4.4 When You Need Which Layer
| If your scenario involves… | Use… |
|---|---|
| A simple transaction with a stranger | L1 + L2 + L3 |
| Trust collapsing after a failure | L4 |
| An ongoing relationship with incentives | L5 |
| Trust recommendations from others | L6 |
| A team, committee, or multi-sig wallet | L7 |
4.5 The Group Trust Extension (GTE)
A trustor's confidence in a group G = {j_1, …, j_m} depends on the group's decision architecture:
- Series (weakest-link):
min(T_j) · κ - Parallel (redundancy):
(1 − ∏(1 − T_j)) · κ - Quorum (k-of-m):
P(X ≥ k) · κwithX ~ BetaBin(m, α, β) - Custom: any monotone
f(T_j) · κ
4.6 The Unification Theorem
from trustlib_mas import verify_unification
print(verify_unification())
# {'specialisation': True, 'bayesian_consistency': True,
# 'strategic_consistency': True, 'bounds': True}
05Your First Trust Decision
5.1 The Scenario
A buyer on Amazon is considering an $800 camera from an unknown seller. The seller has 130 positive reviews and 20 negative reviews. If the camera works, the buyer gains $100 in value; if it's defective, the buyer loses the full $800.
5.2 The Code
from trustlib_mas import Trustee, Trustor, TrustScenario
seller = Trustee(
id="seller", a=130, b=20, discount_factor=0.8
)
buyer = Trustor(
id="buyer", trust_propensity=0.6, risk_aversion=0.2
)
scenario = TrustScenario(
name="Amazon Camera", trustor=buyer, target=seller,
U_win=100, U_loss=-800, stakes=800,
)
decision, trust, eu = scenario.run()
print(f"Effective trust: {trust:.3f}") # 0.372
print(f"Expected utility: ${eu:.2f}") # -465.20
print(f"Decision: {'BUY' if decision else 'DO NOT BUY'}")
5.3 Inspecting the Result
report = scenario.report()
for key, val in report.items():
print(f"{key}: {val}")
Output:
name: Amazon Camera
effective_trust: 0.372...
expected_utility: -465.2
threshold: 160.0
decision: False
06Understanding the Trustee
6.1 Two Ways to Specify Trust
Method A — Beta parameters:
seller = Trustee("seller", a=130, b=20)
seller.bayes_mean() # 0.867
Method B — Explicit trust:
car = Trustee("car")
car.trust = 0.65
car.current_trust() # 0.65
6.2 The Three Cognitive Traits
ceo = Trustee("ceo", A=0.9, B=0.3, I=0.8)
P = ceo.perceived_trustworthiness(alpha=0.7, beta=0.2, gamma=0.1)
# P = 0.7*0.9 + 0.2*0.3 + 0.1*0.8 = 0.77
6.3 The Beta Parameters
| Situation | a | b |
|---|---|---|
| No history | 1 | 1 |
| 10 successes, 0 failures | 11 | 1 |
| 100 successes, 5 failures | 101 | 6 |
| 50/50 split | 50 | 50 |
6.4 Updating with Evidence
seller = Trustee("seller", a=1, b=1)
seller.update_bayes(success=True) # a=2, b=1
seller.update_bayes(success=False) # a=2, b=2
seller.update_bayes(success=True, lam=0.9)
6.5 The Discount Factor
| Trustee type | Typical δ |
|---|---|
| Established seller, repeat business | 0.9–0.95 |
| Regular contractor | 0.8–0.9 |
| One-off transaction | 0.5–0.7 |
| Untraceable anonymous | 0.3–0.5 |
6.6 The Build/Destroy Rates
| Scenario | k_build | k_destroy | Ratio |
|---|---|---|---|
| Human–robot | 0.1 | 0.8 | 8:1 |
| Human–human (team) | 0.15 | 0.45 | 3:1 |
| Institutional trust | 0.05 | 0.30 | 6:1 |
07Understanding the Trustor
7.1 Trust Propensity (τ)
| τ | Interpretation |
|---|---|
| 0.2–0.4 | Cautious, skeptical |
| 0.5 | Neutral |
| 0.6–0.8 | Trusting |
| 0.9–1.0 | Highly trusting |
7.2 Risk Aversion (ρ)
| ρ | Interpretation |
|---|---|
| 0.05 | Risk-tolerant, speculative |
| 0.15–0.25 | Moderate |
| 0.4–0.6 | Conservative, safety-critical |
| 0.8+ | Highly risk-averse |
7.3 Strategic Parameters
beta_s | Behavior |
|---|---|
| 2 | Very gradual transition |
| 10 | Moderate (default) |
| 20 | Close to a hard switch |
| 100+ | Essentially a step function |
7.4 Combining Multiple Trustors
ceo = Trustee("ceo", A=0.9, B=0.3, I=0.8)
for τ, label in [(0.3, "veteran"), (0.8, "newbie")]:
trustor = Trustor(label, trust_propensity=τ)
sc = TrustScenario("CEO", trustor, ceo, U_win=100, U_loss=-50, stakes=100)
print(f"{label}: trust={sc.target_trust():.3f}")
08Making Decisions with TrustScenario
8.1 The Constructor
TrustScenario(
name: str, trustor: Trustor, target: Trustee | TrustGroup,
U_win: float = 1.0, U_loss: float = -1.0,
stakes: float | None = None,
alpha: float = 0.7, beta: float = 0.2, gamma: float = 0.1,
)
8.2 The Decision Rule
EU = T_eff · U_win + (1 − T_eff) · U_loss ≥ ρ · S
8.3 Reading the Decision
decision | Meaning |
|---|---|
True | Expected utility exceeds threshold → rely on trustee |
False | Expected utility is below threshold → decline |
False decision does not
mean the trustee is untrustworthy. It means the risk/reward profile for
this trustor under these stakes does not justify reliance.
8.4 Sensitivity Analysis
seller = Trustee("seller", a=130, b=20, discount_factor=0.8)
for ρ in [0.05, 0.1, 0.2, 0.3, 0.5]:
trustor = Trustor("t", trust_propensity=0.6, risk_aversion=ρ)
sc = TrustScenario("sweep", trustor, seller, 100, -800, 800)
print(f"ρ={ρ:.2f} → trust={sc.target_trust():.3f}")
09Working with Groups
9.1 The Constructor
TrustGroup(
members: list[Trustee],
aggregation: AggregationType = AggregationType.SERIES,
quorum_k: int | None = None, correlation_rho: float = 0.0,
cohesion_pen: float = 0.0, cohesion_rew: float = 0.0,
cohesion_tau: float = 0.0, entropy_override: float | None = None,
custom_aggregator: Callable | None = None,
collective_discount: float | None = None,
apply_collective_strategic: bool = False,
delta_star: float = 0.708, beta_s: float = 10.0,
)
9.2 The Bare Minimum
from trustlib_mas import Trustee, TrustGroup, AggregationType
trucks = [Trustee(f"T{i}", a=92, b=8) for i in range(4)]
trucks.append(Trustee("T4", a=40, b=60))
platoon = TrustGroup(trucks, aggregation=AggregationType.SERIES)
print(platoon.aggregate_trust()) # 0.40
9.3 Inspecting Components
print(platoon.individual_trusts())
print(platoon.aggregate_raw())
print(platoon.cohesion_factor())
print(platoon.aggregate_trust())
9.4 Adding Cohesion Penalty
platoon = TrustGroup(trucks, aggregation=AggregationType.SERIES,
cohesion_pen=10.0, cohesion_tau=0.02)
print(platoon.cohesion_factor()) # ~0.79
print(platoon.aggregate_trust()) # ~0.317
9.5 Groups of Groups
def two_level(scores):
a = min(scores[:3])
b = min(scores[3:])
return min(a, b)
g = TrustGroup(members, aggregation=AggregationType.CUSTOM,
custom_aggregator=two_level)
10Aggregation Architectures in Depth
10.1 Series (Weakest-Link)
Formula: T = min(T_j) × κ
Use when: success requires every member to succeed — platoons, surgical teams, pipelines.
10.2 Parallel (Redundancy)
Formula: T = (1 − ∏(1 − T_j)) × κ
Use when: success requires at least one member to succeed — sensor arrays, backup systems.
10.3 Quorum (k-of-m)
g = TrustGroup(signers, aggregation=AggregationType.QUORUM,
quorum_k=5, correlation_rho=0.2)
10.4 Custom
from trustlib_mas import harmonic_mean
g = TrustGroup(team, aggregation=AggregationType.CUSTOM,
custom_aggregator=harmonic_mean)
10.5 Choosing the Right Architecture
| Decision structure | Architecture |
|---|---|
| All must succeed | SERIES |
| Any one suffices | PARALLEL |
| k must agree | QUORUM |
| Average/median/harmonic | CUSTOM |
| Safety-critical team | SERIES + high ν_pen |
| Advisory panel | QUORUM + ν_rew > 0 |
11The Cohesion–Diversity Function
11.1 The Formula
κ = min{ 1, exp( −ν_pen · max(0, σ² − τ) + ν_rew · H ) }
11.2 What Each Parameter Does
| Parameter | Effect | Typical range |
|---|---|---|
cohesion_pen | Penalizes high variance | 2–50 |
cohesion_rew | Rewards high entropy | 0–10 |
cohesion_tau | Variance tolerance | 0.01–0.10 |
11.3 Entropy Source
ts = [0.9, 0.7, 0.5, 0.3]
# normalized: [0.375, 0.292, 0.208, 0.125]
# H = -Σ p log p ≈ 1.32 nats
# For classification scenarios (True/False labels):
g = TrustGroup(..., entropy_override=0.673)
11.4 A Decision Table
| Scenario | ν_pen | ν_rew | τ |
|---|---|---|---|
| Surgical team | 50 | 0 | 0.01 |
| Platoon | 10 | 0 | 0.02 |
| DAO multi-sig | 2 | 0 | 0.02 |
| Advisory panel | 5 | 5 | 0.10 |
| Sensor array | 1 | 0 | 0.05 |
12Correlated Quorum Models
12.1 The Correlation Parameter ρ
| Scenario | ρ |
|---|---|
| Independent sensors | 0.0 |
| Signers in a DAO | 0.2 |
| Members of the same firm | 0.3 |
| Family members | 0.5 |
12.2 The Effect on Quorum Trust
signers = [Trustee(f"S{i}", a=90, b=10) for i in range(6)]
signers.append(Trustee("M", a=60, b=40))
signers.extend([Trustee(f"U{i}", a=40, b=60) for i in range(2)])
for ρ in [0.0, 0.1, 0.2, 0.3, 0.5]:
g = TrustGroup(signers, aggregation=AggregationType.QUORUM,
quorum_k=5, correlation_rho=ρ)
print(f"ρ={ρ:.1f} raw={g.aggregate_raw():.4f}")
# ρ=0.0 raw=0.9636
# ρ=0.1 raw=0.9448
# ρ=0.2 raw=0.9113
# ρ=0.3 raw=0.8711
# ρ=0.5 raw=0.7982
13Temporal Dynamics and Trust Recovery
13.1 Simulating a Failure
car = Trustee("car", k_build=0.1, k_destroy=0.8)
car.trust = 0.65
car.asymmetric_dynamics(success=False)
print(car.trust) # 0.130
13.2 Simulating Recovery
for i in range(20):
car.asymmetric_dynamics(success=True)
print(f"Ride {i+1}: T = {car.trust:.3f}")
13.3 Closed-Form Recovery Time
car.trust = 0.13
t = car.recovery_time(target=0.8, k_build=0.1)
print(f"{t:.2f} rides to recover to 0.8") # 14.70
13.4 Choosing Build/Destroy Rates
| Domain | k_build | k_destroy |
|---|---|---|
| Robotaxi | 0.1 | 0.8 |
| Chatbot | 0.2 | 0.6 |
| Team member | 0.15 | 0.45 |
| Institutional | 0.05 | 0.30 |
asymmetric_dynamics and
update_bayes for the same event. Choose one: use
update_bayes for a principled Bayesian count, or
asymmetric_dynamics for a phenomenological trust level.
14Network Propagation
14.1 Setting Up a Network
from trustlib_mas import TrustNetwork
net = TrustNetwork(n_agents=4)
net.set_direct(0, 1, 0.9)
net.set_direct(0, 2, 0.4)
net.set_direct(1, 2, 0.95)
net.set_direct(1, 3, 0.7)
net.set_direct(2, 3, 0.85)
14.2 One-Step and Iterated Updates
net.update(mu=0.5) # one damped step
net.iterate(steps=10, mu=0.5) # ten steps
T^(t+1) = μ · T_direct + (1 − μ) · T_indirect
μ = 1→ ignore network (pure direct)μ = 0→ ignore direct (pure indirect)μ = 0.5→ balanced (typical)
14.3 Combining with TrustScenario
net.iterate(steps=5)
propagated = net.direct[0][3]
target = Trustee("target")
target.trust = propagated
sc = TrustScenario("Propagated", trustor, target,
U_win=100, U_loss=-200, stakes=200)
15Simulation and Evaluation Toolkit
15.1 Proof-of-Concept Simulation
from trustlib_mas import simulate_comparison
results = simulate_comparison(
n_scenarios=2000, seed=42, rho_true=0.2,
)
for name, r in results.items():
print(f"{name:<12} acc={r['accuracy']:.3f} "
f"brier={r['brier']:.3f} auc={r['roc_auc']:.3f}")
# unified acc=0.907 brier=0.074 auc=0.939
# average acc=0.789 brier=0.121 auc=0.881
# minmax acc=0.842 brier=0.150 auc=0.851
# binomial acc=0.851 brier=0.106 auc=0.901
15.2 Classification Metrics
from trustlib_mas import roc_auc, precision_recall
labels = [1, 0, 1, 1, 0, 1, 0, 1]
scores = [0.9, 0.3, 0.8, 0.7, 0.4, 0.85, 0.2, 0.75]
print(f"ROC-AUC: {roc_auc(labels, scores):.4f}")
prec, rec = precision_recall(labels, scores, threshold=0.5)
print(f"Precision: {prec:.4f} Recall: {rec:.4f}")
15.3 Repeated Simulation with 95% Confidence Intervals
from trustlib_mas import run_repeated_sim
summary = run_repeated_sim(
n_scenarios=2000, n_repeats=50, base_seed=0, rho_true=0.2,
)
for model, metrics in summary.items():
acc, acc_hw = metrics["accuracy"]
br, br_hw = metrics["brier"]
auc, auc_hw = metrics["roc_auc"]
print(f"{model:<12}"
f"{acc:>10.3f} ± {acc_hw:<8.3f}"
f"{br:>10.3f} ± {br_hw:<8.3f}"
f"{auc:>10.3f} ± {auc_hw:<8.3f}")
15.4 Ablation Study
from trustlib_mas import run_ablation_study
results = run_ablation_study(n_scenarios=2000, seed=42)
for name, r in results.items():
print(f"{name:<24} acc={r['accuracy']:.3f} brier={r['brier']:.3f}")
# full acc=0.902 brier=0.073
# no_cohesion acc=0.856 brier=0.095
# no_correlated_quorum acc=0.871 brier=0.088
# no_strategic acc=0.847 brier=0.101
# no_temporal acc=0.864 brier=0.092
15.5 Robustness to Model Misspecification
from trustlib_mas import run_robustness_check
results = run_robustness_check(n_scenarios=2000, seed=42)
for regime, r in results.items():
print(f"{regime:<16} acc={r['accuracy']:.3f} brier={r['brier']:.3f}")
acc_matched = results["matched"]["accuracy"]
acc_misspec = results["misspecified"]["accuracy"]
drop = (acc_matched - acc_misspec) / acc_matched * 100
print(f"\nRelative accuracy drop: {drop:.1f}%")
# matched acc=0.906 brier=0.074
# misspecified acc=0.883 brier=0.089
# Relative accuracy drop: 2.5%
15.6 Runtime Considerations
| Function | Default n_scenarios | Typical runtime |
|---|---|---|
simulate_comparison | 2,000 | < 1 s |
run_repeated_sim (50 repeats) | 2,000 | ~30 s |
run_ablation_study | 2,000 | ~5 s |
run_robustness_check | 2,000 | ~2 s |
16Verifying the Unification Theorem
The theorem has four parts, each verified numerically:
- Specialisation — for
m = 1, the GTE reduces to the dyadic model. - Bayesian consistency — the group Bayesian update with
m = 1matches the dyadic update. - Strategic consistency — the collective discount factor equals the individual δ when
m = 1. - Bounds — all trust scores remain in
[0, 1].
from trustlib_mas import verify_unification
for part, ok in verify_unification().items():
print(f" {part:<24} [{'PASS' if ok else 'FAIL'}]")
# specialisation [PASS]
# bayesian_consistency [PASS]
# strategic_consistency [PASS]
# bounds [PASS]
17Common Recipes
17.1 Trust a Seller from Reviews
def seller_trust(pos, neg, tau=0.6, rho=0.2, price=800, surplus=100):
seller = Trustee("seller", a=pos + 1, b=neg + 1, discount_factor=0.8)
buyer = Trustor("buyer", trust_propensity=tau, risk_aversion=rho)
sc = TrustScenario("Amazon", buyer, seller,
U_win=surplus, U_loss=-price, stakes=price)
return sc.run()
17.2 Evaluate a Multi-Sig Wallet
def multisig_trust(trusts, k, rho=0.2):
members = [Trustee(f"S{i}", a=100*t, b=100*(1-t))
for i, t in enumerate(trusts)]
g = TrustGroup(members, aggregation=AggregationType.QUORUM,
quorum_k=k, correlation_rho=rho,
cohesion_pen=2.0, cohesion_tau=0.02)
return g.aggregate_trust()
17.3 Simulate a Failure-and-Recovery Trajectory
def trajectory(initial, failure_at, n_rides=30):
car = Trustee("car", k_build=0.1, k_destroy=0.8)
car.trust = initial
history = [car.trust]
for i in range(n_rides):
car.asymmetric_dynamics(success=(i != failure_at))
history.append(car.trust)
return history
17.4 Bayesian A/B Comparison
def compare(a_s, a_f, b_s, b_f, n_samples=10000):
import random
rng = random.Random(0)
a_wins = 0
for _ in range(n_samples):
pa = rng.betavariate(a_s + 1, a_f + 1)
pb = rng.betavariate(b_s + 1, b_f + 1)
a_wins += int(pa > pb)
return a_wins / n_samples
17.5 Reproducing the Paper's Tables
from trustlib_mas import (
run_repeated_sim, run_ablation_study, run_robustness_check,
)
summary = run_repeated_sim(n_scenarios=2000, n_repeats=50, base_seed=0)
ablation = run_ablation_study(n_scenarios=2000, seed=42)
robustness = run_robustness_check(n_scenarios=2000, seed=42)
18Advanced Usage
18.1 Custom Aggregation with Weights
def weighted_min(scores, weights):
return min(s / w for s, w in zip(scores, weights) if w > 0)
def make_weighted_min(weights):
return lambda scores: weighted_min(scores, weights)
g = TrustGroup(members, aggregation=AggregationType.CUSTOM,
custom_aggregator=make_weighted_min([1.0, 1.0, 0.5, 1.0]))
18.2 Dynamic Group Composition
def step_with_churn(group, arrive=None, depart=None):
members = [m for m in group.members if m.id not in (depart or [])]
if arrive:
members.append(arrive)
return TrustGroup(members, aggregation=group.aggregation,
cohesion_pen=group.cohesion_pen,
cohesion_tau=group.cohesion_tau)
18.3 Subclassing Trustee for Custom Dynamics
class LevyTrustee(Trustee):
jump_size: float = 0.2
jump_prob: float = 0.05
def asymmetric_dynamics(self, success, **kwargs):
super().asymmetric_dynamics(success, **kwargs)
import random
if random.random() < self.jump_prob:
self.trust = max(0.0, self.trust - self.jump_size)
return self.trust
18.4 Calibration via Maximum Likelihood
from itertools import product
def fit_params(dataset, ν_grid, ρ_grid):
best = None
for ν_pen, ν_rew, ρ in product(ν_grid, ν_grid, ρ_grid):
loss = 0.0
for features, y in dataset:
g = TrustGroup(features, aggregation=AggregationType.QUORUM,
quorum_k=len(features)//2+1,
correlation_rho=ρ,
cohesion_pen=ν_pen,
cohesion_rew=ν_rew)
loss += (g.aggregate_trust() - y) ** 2
if best is None or loss < best[0]:
best = (loss, ν_pen, ν_rew, ρ)
return best
19Parameter Calibration Guide
| Parameter | Class | How to Calibrate |
|---|---|---|
a, b | Trustee | Count successes/failures |
A, B, I | Trustee | Survey instruments |
discount_factor | Trustee | Repeated-game data |
k_build, k_destroy | Trustee | Fit to recovery curves |
trust_propensity | Trustor | Disposition survey |
risk_aversion | Trustor | Lottery elicitation |
correlation_rho | TrustGroup | Method of moments |
cohesion_* | TrustGroup | MLE on team performance |
Practical Heuristics When You Have No Data
| Parameter | Heuristic |
|---|---|
τ | 0.5 (neutral) or 0.6 (slightly trusting) |
ρ | 0.2 (moderate) |
δ | 0.8 (established relationship) |
δ* | 0.708 (default) |
β_s | 10 |
k_build | 0.1 |
k_destroy | 0.6 (3:1) to 0.8 (8:1) |
ν_pen | 10 safety-critical, 2 advisory |
ρ_corr | 0.2 |
20Troubleshooting
20.1 "ModuleNotFoundError: No module named 'trustlib'"
You may have upgraded to trustlib-mas but your code still imports the old name.
# Option A: install the shim
pip install trustlib-mas
# Option B: update imports
from trustlib_mas import Trustee # instead of: from trustlib import Trustee
20.2 "ValueError: quorum_k must be set for QUORUM aggregation"
g = TrustGroup(members, aggregation=AggregationType.QUORUM, quorum_k=5)
20.3 "ValueError: custom_aggregator must be provided"
g = TrustGroup(members, aggregation=AggregationType.CUSTOM,
custom_aggregator=harmonic_mean)
20.4 "ValueError: TrustGroup must contain at least one member"
Empty group. Add members or check your construction loop.
20.5 Trust Always 0 or 1
- Are
aandbsensible? - Is
discount_factorbelowdelta_star? - Is
trust_propensityset to something reasonable?
20.6 Cohesion Factor Always 1
- Is
cohesion_pen > 0? - Is the variance actually above
cohesion_tau? - For single-member groups,
κ = 1by definition.
20.7 Correlation Has No Effect
- Is
ρabove1e-6? - Is
aggregation=QUORUM?
20.8 Decision Flips Unexpectedly
U_losssign (should usually be negative)stakestoo small or too largerisk_aversiontoo low
Print scenario.report() to inspect all intermediates.
20.9 Simulation Function Raises NaN
If you see nan in ROC-AUC or precision/recall, your data is
likely all one class. Increase n_scenarios or adjust
rho_true.
20.10 verify_unification() Fails
If any part of the Unification Theorem fails to verify, the core mathematics have been altered (perhaps by a monkey-patch or a subclass). Restore the library to its original state, or file an issue.
21Best Practices
21.1 Model Design
- Start simple. Use just L1–L3 for a first prototype.
- Keep units consistent.
- Sign discipline.
U_lossshould be negative. - Weights sum to 1.
alpha + beta + gamma = 1. - Document parameters. Record where each number came from.
21.2 Coding Practices
- Use dataclasses. Construct in one place and pass around.
- Do not mutate shared trustees. Changes propagate.
- Separate model from data. Parameter values in config.
- Log intermediate values.
scenario.report()is your friend.
21.3 Scientific Practices
- Report calibration. State where each parameter came from.
- Report sensitivity. Show how the decision changes with ρ, ν_pen.
- Use held-out data. Reserve a test set.
- Do not over-claim. A simulation is not empirical validation.
- Cite the framework and paper version.
21.4 Reproducibility
- Always fix
seedwhen running simulations. - Report
n_scenariosandn_repeats. - Include
trustlib_mas.__version__andtrustlib_mas.__paper_version__in your methods.
22Frequently Asked Questions
Q1. Do I need all seven layers?
No. Start with L1–L3 for a basic model. Add L4–L7 as needed.
Q2. What's the difference between trust and a/b?
a/b is a Bayesian count that can be updated.
trust is an explicit override.
Q3. Why is my decision False even though the trustee has high trust?
Because expected utility, not trust alone, drives the decision.
Q4. Why does the paper report 0.243 for the platoon but the library reports 0.317?
The paper's σ² = 0.07 is illustrative; the library computes the exact variance (≈ 0.043).
Q5. Can I use the library for reinforcement learning?
Yes, as a trust-value function.
Q6. How do I model a Sybil attack?
Low a, high b, and very low
discount_factor (0.2). The strategic override will suppress
trust.
Q7. What if I don't know delta_star?
Use 0.708 for the standard PD payoff. For other games,
compute (T-R)/(T-P).
Q8. Can I model mixed human-AI teams?
Yes. Humans and AIs are both Trustee instances.
Q9. How do I test my model?
Use test_trustlib_mas.py as a template. Verify bounds and
unification.
Q10. Can I use the library commercially?
Yes — MIT license.
Q11. How do I cite the library?
See the Citation section in the README. Cite the manuscript too.
Q12. Why is the package called trustlib-mas but the import trustlib_mas?
Python does not allow hyphens in module names.
Q13. Will from trustlib import ... still work?
Yes, as long as the shim ships with the package.
Q14. How do I know which paper version the library targets?
Check trustlib_mas.__paper_version__. For v1.1.0,
this is "v3".
Q15. How do I run the ablation study quickly?
Use run_ablation_study(n_scenarios=500).
23Reference Tables
23.1 Aggregation Types
| Type | Formula | Use case |
|---|---|---|
SERIES | min(T_j) × κ | All-must-succeed |
PARALLEL | (1 − ∏(1−T_j)) × κ | Any-succeeds |
QUORUM | P(X ≥ k) × κ | k-of-m |
CUSTOM | f(T_j) × κ | Anything monotone |
23.2 Strategic Factor Values
| δ | Φ(δ) at β_s=10, δ*=0.708 |
|---|---|
| 0.3 | 0.016 |
| 0.5 | 0.111 |
| 0.6 | 0.254 |
| 0.708 | 0.500 |
| 0.8 | 0.715 |
| 0.9 | 0.874 |
| 0.95 | 0.922 |
23.3 Cohesion Penalty Examples
| ν_pen | κ (σ²=0.05, τ=0) |
|---|---|
| 1 | 0.951 |
| 5 | 0.779 |
| 10 | 0.607 |
| 20 | 0.368 |
| 50 | 0.082 |
23.4 Quorum Survival with Correlation
| ρ | P(X ≥ 5) |
|---|---|
| 0.0 | 0.96 |
| 0.1 | 0.94 |
| 0.2 | 0.91 |
| 0.3 | 0.87 |
| 0.5 | 0.80 |
23.5 Simulation Function Signatures
| Function | Signature |
|---|---|
simulate_comparison | (n_scenarios=2000, seed=0, rho_true=0.2, n_repeats=1) |
run_repeated_sim | (n_scenarios=2000, n_repeats=50, base_seed=0, rho_true=0.2) |
run_ablation_study | (n_scenarios=2000, seed=42, rho_true=0.2) |
run_robustness_check | (n_scenarios=2000, seed=42, rho_true=0.2) |
verify_unification | (tolerance=1e-9) |
24Glossary
| Term | Definition |
|---|---|
| Trustee | The agent being evaluated |
| Trustor | The agent making the decision |
| Effective trust | The final trust score after all layers |
| Cohesion factor (κ) | Multiplier reflecting group coordination |
| Correlation (ρ) | Degree of dependence among group members |
| Discount factor (δ) | Trustee's long-term orientation |
| Betrayal threshold (δ*) | Minimum δ for sustained cooperation |
| Trust propensity (τ) | Trustor's baseline willingness |
| Brier score | MSE of probabilistic predictions |
| ROC-AUC | Area under the ROC curve |
| Weakest-link | Series aggregation (min) |
| Redundancy | Parallel aggregation (1 − ∏) |
| GTE | Group Trust Extension |
| Ablation | Removing one component to measure its contribution |
| Misspecification | Data-generating process differing from model assumptions |
AComplete Working Example
"""
complete_example.py — Exercises every major feature of trustlib-mas v1.1.0.
Run: python complete_example.py
"""
import trustlib_mas
from trustlib_mas import (
Trustee, Trustor, TrustGroup, TrustScenario, TrustNetwork,
AggregationType, harmonic_mean,
simulate_comparison, run_repeated_sim, run_ablation_study,
run_robustness_check, verify_unification, roc_auc, precision_recall,
)
def main():
print(f"trustlib_mas v{trustlib_mas.__version__} "
f"(paper {trustlib_mas.__paper_version__})")
print("\n[1] Unification check")
for part, ok in verify_unification().items():
print(f" {part:<24} {'PASS' if ok else 'FAIL'}")
print("\n[2] Dyadic: e-commerce seller")
buyer = Trustor("buyer", trust_propensity=0.6, risk_aversion=0.2)
seller = Trustee("seller", a=130, b=20, discount_factor=0.8)
sc = TrustScenario("Amazon", buyer, seller,
U_win=100, U_loss=-800, stakes=800)
print(" ", sc.report())
print("\n[3] Asymmetric dynamics: robotaxi")
car = Trustee("car", k_build=0.1, k_destroy=0.8)
car.trust = 0.65
car.asymmetric_dynamics(success=False)
print(f" After failure: T = {car.trust:.3f}")
print(f" Recovery time: {car.recovery_time(0.8):.2f} rides")
print("\n[4] Group: platoon (series)")
trucks = [Trustee(f"T{i}", a=92, b=8) for i in range(4)]
trucks.append(Trustee("T4", a=40, b=60))
platoon = TrustGroup(trucks, aggregation=AggregationType.SERIES,
cohesion_pen=10.0, cohesion_tau=0.02)
print(f" T_agg = {platoon.aggregate_trust():.3f}")
print("\n[5] Group: DAO multi-sig (correlated quorum)")
signers = [Trustee(f"S{i}", a=90, b=10) for i in range(6)]
signers.append(Trustee("M", a=60, b=40))
signers.extend([Trustee(f"U{i}", a=40, b=60) for i in range(2)])
dao = TrustGroup(signers, aggregation=AggregationType.QUORUM,
quorum_k=5, correlation_rho=0.2,
cohesion_pen=2.0, cohesion_tau=0.02)
print(f" T_agg = {dao.aggregate_trust():.3f}")
print("\n[6] Group: surgical team (custom harmonic)")
team = TrustGroup(
[Trustee("Surgeon", a=95, b=5), Trustee("Anes", a=90, b=10),
Trustee("Nurse1", a=98, b=2), Trustee("Nurse2", a=70, b=30),
Trustee("Perf", a=85, b=15)],
aggregation=AggregationType.CUSTOM,
custom_aggregator=harmonic_mean,
cohesion_pen=5.0, cohesion_tau=0.01,
)
print(f" T_agg = {team.aggregate_trust():.3f}")
print("\n[7] Network propagation")
net = TrustNetwork(4)
net.set_direct(0, 1, 0.9); net.set_direct(0, 2, 0.4)
net.set_direct(1, 2, 0.95); net.set_direct(1, 3, 0.7)
net.set_direct(2, 3, 0.85)
net.iterate(steps=5, mu=0.5)
print(f" Propagated 0→3: {net.direct[0][3]:.4f}")
print("\n[8] Simulation (single seed)")
res = simulate_comparison(n_scenarios=1000, seed=42)
for name, r in res.items():
print(f" {name:<10} acc={r['accuracy']:.3f} "
f"brier={r['brier']:.3f} auc={r['roc_auc']:.3f}")
print("\n[9] Repeated simulation (5 repeats, 95% CI)")
summary = run_repeated_sim(n_scenarios=500, n_repeats=5, base_seed=0)
for model, m in summary.items():
acc, hw = m["accuracy"]
print(f" {model:<10} acc={acc:.3f} ± {hw:.3f}")
print("\n[10] Ablation study")
for name, r in run_ablation_study(n_scenarios=500).items():
print(f" {name:<22} acc={r['accuracy']:.3f}")
print("\n[11] Robustness check")
rob = run_robustness_check(n_scenarios=500)
for regime, r in rob.items():
print(f" {regime:<14} acc={r['accuracy']:.3f}")
if __name__ == "__main__":
main()
BFurther Reading
- Mayer, Davis, & Schoorman (1995) — Cognitive antecedents of trust
- Jøsang & Ismail (2002) — Beta reputation systems
- Axelrod (1984) — Evolution of cooperation
- Surowiecki (2004) — Wisdom of crowds
- Ponnambalam et al. (2021) — Prior MAS trust framework
- Cheng et al. (2021, AAMAS) — General trust framework with epistemic logic
- Skellam (1948) — Beta-binomial distribution
- Wang (2026, v3) — The unified dyadic-and-collective framework (manuscript)
CVersion History
| Version | Date | Notes |
|---|---|---|
| 1.0.0 | 2026 | Initial release as trustlib |
| 1.1.0 | 2026 | Renamed to trustlib-mas; aligned with paper v3; added simulation & evaluation toolkit |