Skip to main content

robustrep

Robust, transport-agnostic reputation scoring for AI agents.

Feed it any table of (rater, ratee, value, scale, tag, ts, evidence_uri, source) and it returns a robust score per ratee that resists Sybil raters and evidence-free ratings. Ships with a Base-chain ERC-8004 adapter and a reproducible report.

Status: v0.1.1 released on PyPI. Design spec and plan live in the parent workspace; a summary is in reports/latest/report.md. Release notes, including the security fixes in 0.1.1: CHANGELOG.md.

Install

pip install robustrep

Library

import pandas as pd
from robustrep import Config, score

records = pd.DataFrame([...])  # columns: rater, ratee, value, scale, tag, ts, evidence_uri, source
result = score(records, Config())

Base ERC-8004 report

robustrep fetch  --db data/base.db          # pull events (resumable)
robustrep score  --db data/base.db --out scores.csv
robustrep report --db data/base.db --out-dir reports

The default endpoint list is rotated automatically and the eth_getLogs window adapts per endpoint; --rpc-url (repeatable) replaces the list and --chunk caps the window. RPC endpoint hostnames appear in the public report and scores.json; do not use an endpoint whose hostname embeds an account id or key.

Rater profiles (first-seen time and funder per rater, for sybil clustering) come from Alchemy when ALCHEMY_API_KEY is set — its free plan covers Base (2.5 requests/sec; ~13k raters in about 1.5 h). Blockscout closed its free Base API in 2026-10 and Etherscan's free plan never covered Base, so Alchemy is now the practical source. Pick one explicitly with fetch --profile-source {auto,alchemy,blockscout,etherscan,none}; auto prefers an Etherscan key, then an Alchemy key, then keyless Blockscout. The Alchemy key is read from the environment only (no flag), redacted from urllib3's debug log and from robustrep's own log records that echo server text, and never appears in an error message — Alchemy puts it in the request URL's path, so nothing that quotes a URL is ever raised or logged.

A rater's funder is "who controls or funded it", by one of two rules, recorded per row in raters.funder_kind. transfer: the from of the address's first incoming transfer (the original rule). owner: since October 2026 nearly every new rater on Base is a smart-contract account that never received a transfer (230/230 sampled on 2026-10-13; 55/60 are Coinbase Smart Wallets), so fetch runs a second pass that reads the account's controlling key over plain RPC (ownerAtIndex(0..3), then owner(); one 50-address batch per chunk, each entry's outcome its own, a reverting call never retried) and stores it as the funder in its own namespace (owner:<address>) — on the sampled wallets 55 accounts resolved to only 4 keys. Wallets sharing a key cluster exactly as wallets sharing a first funder do, but only among themselves: the key is whatever the rater's own contract reports, so it is never compared with a transfer-kind funder. The bundlers and paymaster behind their first transactions are shared infrastructure and are never used (nor are internal transfers, which would include a paymaster's gas advance). An account with no owner is marked none (passkey-controlled accounts land here) and not looked up again; a legacy row's first_seen_ts is preserved. The report's Provenance lists the row count per kind.

Latest scores: reports/latest/scores.json, also served at https://iamdongwang.github.io/robustrep/reports/latest/scores.json

Security considerations

Everything robustrep reads is written by untrusted parties: on-chain values, tags, evidence URIs and addresses, plus whatever the RPC/Blockscout endpoints and evidence hosts return.

robustrep fetch makes outbound HTTP from your machine to evidence URIs chosen by the rated party. Those go through an SSRF guard (scheme/host allowlist, parser cross-check, canonical rebuild, refusal of private/reserved addresses, manual redirects, a size cap and per-socket-operation timeouts — not a wall-clock bound). Its one known SSRF bypass, DNS rebinding, is unmitigated in v0.1 — so run fetch on a host with no privileged reach into an internal network. API keys should come from the environment (ETHERSCAN_API_KEY), never the source tree; --etherscan-key is an escape hatch that takes precedence over the environment and is visible to anyone who can run ps.

Full threat model and private reporting instructions: SECURITY.md.

Metadata

Release files for robustrep 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for robustrep 0.2.2
File Size Uploaded
robustrep-0.2.2.tar.gz 343.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for robustrep 0.2.2
File Interpreter ABI Platform
robustrep-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 522.9 kB

Release files / robustrep-0.2.2.tar.gz

Download URL robustrep-0.2.2.tar.gz
Size 343.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0c7d138af4c7702a790f20a3699f5cb648bcba1f358427395307d12974f90cc5
BLAKE2b-256 checksum
How to use checksums
40d0503260f00643a09fdbd9c5329750f5307980894fcb6b5ab55bea5a5e3746
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / robustrep-0.2.2-py3-none-any.whl

Download URL robustrep-0.2.2-py3-none-any.whl
Size 179.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe121e053eb580f82dae9ffd2f1a974ff4092389251f64d11b4186650bef50c9
BLAKE2b-256 checksum
How to use checksums
79fd33fccfbfb215297807aec326817189a679c065250fec8aba719df800d0ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page