English | νκ΅μ΄ | ζ₯ζ¬θͺ | δΈζ
Ethereum SDK extensions for ERC-8004: Trustless Agents β typed registry reads, plus a policy-driven reputation calculator, as extensions to each ecosystem's canonical Ethereum SDK.
- Why
- Quickstart
- The two-layer contract
- Packages
- Design principles
- The golden vectors β a conformance challenge
- Porting to a new language
- A note on live numbers
- Why no score? Read the theory
- Development
- Status
- Sibling project
- License
AI agents are starting to hire, pay, and delegate to other agents. ERC-8004 gives them an on-chain trust layer β identity, reputation, and validation registries β but reading that data is only half the problem. The other half is turning raw, Sybil-able, inconsistently-scaled feedback into a number you can actually act on, without handing that judgment call to a third-party black box.
Most "reputation" tooling collapses this into a single opaque score. This SDK refuses to: it hands you the facts, lets you declare your own aggregation policy, and returns a result that always carries its own uncertainty and caveats β computed the same way in every language it ships in.
Pick your stack β all three compute the identical calculator against the identical golden vectors (see below).
npm install agent-reputation viemimport { createPublicClient, http } from "viem";
import { base } from "viem/chains";
import { erc8004Actions, calculateReputation } from "agent-reputation";
const client = createPublicClient({ chain: base, transport: http() }).extend(
erc8004Actions(),
);
const feedback = await client.getAgentFeedback({ agentId: 1n });
const rep = calculateReputation(feedback, { witnessCap: 1 });pip install web3-agent-reputationfrom web3 import Web3
from web3_agent_reputation import ERC8004Module, calculate_reputation
w3 = Web3(Web3.HTTPProvider("https://mainnet.base.org"), external_modules={"erc8004": ERC8004Module})
feedback = w3.erc8004.get_agent_feedback(1)
rep = calculate_reputation(feedback, witness_cap=1)[dependencies]
alloy-agent-reputation = "0.2"use alloy_agent_reputation::Erc8004ProviderExt;
use alloy_agent_reputation::calculator::{calculate_reputation, Policy};
let feedback = provider.get_agent_feedback(agent_id, 200, 0).await?;
let rep = calculate_reputation(&feedback, Policy { witness_cap: Some(1.0), ..Default::default() })?;See examples/ (TypeScript), packages/py/examples/,
and packages/rs/examples/ for full runnable pre-delegation-guard
scripts in each language.
Facts layer β thin typed reads through your existing client; no opinions:
const client = createPublicClient({ chain: base, transport: http() }).extend(
erc8004Actions(),
);
await client.getAgent({ agentId: 1n });
await client.getAgentFeedback({ agentId: 1n });
await client.getRegistrationFile({ agentId: 1n }); // verified: true | false | nullCalculator layer β a pure function; your policy in, evidence-rich result out:
const rep = calculateReputation(feedback, {
witnessCap: 1,
credibility: activitySqrt(distinctCounts),
});
// β { expectation: 0.665, uncertainty: 0.179, witnesses: 20,
// topWitnessShare: 0.15, caveats: [...], policy: { ...echoed } }Neither layer ever returns a bare pass/fail or a single "trust this agent" boolean β see Design principles.
| Language | Host SDK | Package | Status |
|---|---|---|---|
| TypeScript | viem actions | agent-reputation (npm) |
published β v0.2.0 |
| Python | web3.py external module | web3-agent-reputation (PyPI) |
published β v0.2.0 |
| Rust | alloy extension trait | alloy-agent-reputation (crates.io) |
published β v0.2.0 |
All three pass the same golden vectors and the same conformance suite β see CHANGELOG.md for the release-by-release detail.
No signing, no writes, in any language, ever. No
WalletClient(or its Python/Rust equivalent) is ever imported or accepted anywhere in this SDK. A write-capable extension β if one ever exists β would live in a different package, with a different, explicit opt-in.
Every reputation result carries
uncertainty, witness statistics, mandatory honesty caveats, and the echoed policy that produced it β the reproducibility manifest. A library that quietly compresses "20 witnesses, one of whom submitted 15% of all entries" into a single number is making a judgment call it has no business making on the consumer's behalf.
Every implementation accumulates in the same deterministic order and must reproduce the golden test vectors in
vectors/exactly (3-decimal tolerance). A second language ships only after passing them in CI β see below.
This library computes what you asked for, under a policy you declared. It does not define "the" score for any agent, and it never will.
vectors/ is a frozen snapshot of real ERC-8004 feedback (Base mainnet,
agents 0β9) plus the exact expected output of the reference calculator, for two policy
variants, to three decimal places. It's the cross-language contract that makes
"agent-reputation for viem," "web3-agent-reputation for web3.py," and
"alloy-agent-reputation for alloy" the same calculator wearing three different host
SDKs, rather than three independent reimplementations that happen to agree most of the
time.
A new language passes vectors/ + conformance/
or it doesn't ship. Bit-for-bit golden-vector reproduction, plus byte-matching caveat
strings, verification cases, and API surface (see
conformance/README.md), are not aspirational β they're the
acceptance bar. If you implement this calculator against another chain-SDK or in
another ecosystem and reproduce every row in
vectors/base-2026-07-13.json, open an issue β that's
the bar for a fourth entry in the package table above.
Numbers from a live getAgentFeedback call will drift over time β on-chain feedback
only ever grows, so an agent's witnesses, expectation, and uncertainty today will
not match this README, the examples' captured transcripts, or even themselves an hour
from now. That's expected, not a bug. The one thing that does not drift is
vectors/base-2026-07-13.json: a frozen snapshot,
timestamped in its own filename, that every language's conformance suite checks
against instead of the live chain.
If you're wondering why this SDK insists on expectation + uncertainty + caveats
instead of just handing you a single "trust score," the reasoning β with full mathematical
background β is in docs/THEORY.md.
pnpm install
pnpm run lint # ALL THREE languages: eslint+prettier, ruff check+format, fmt+clippy
pnpm -r typecheck # tsc --noEmit, TypeScript package
pnpm -r test # vitest + pytest + cargo test, golden-vector conformance included
pnpm -r test:live # live smoke tests against public Base RPCs (not run in CI)
pnpm -r build # compile TypeScript to dist/Project layout:
packages/tsβ the TypeScript package (agent-reputation): facts layer (viem actions) + calculator layer + golden-vector conformance tests.packages/pyβ the Python package (web3-agent-reputation): facts layer (web3.py external module) + calculator layer, numerically identical topackages/ts.packages/rsβ the Rust package (alloy-agent-reputation): facts layer (alloy provider extension trait) + calculator layer, same golden vectors.vectors/β the cross-language golden-vector conformance fixtures.conformance/β the second half of the cross-language contract: canonical caveat strings, verification test cases, and the API-surface manifest β seeconformance/README.md.docs/THEORY.mdβ the background theory behind the calculator, written for readers with the mathematical background included (Beta distribution, conjugacy, subjective logic).examples/β runnable, documented example scripts in every language (seeexamples/README.md)..github/workflows/β CI (ci.yml) and a dry-run-only manual release workflow (release.yml); see CHANGELOG.md for the "flip at release" note.
v0.2.0 β published to all three registries. agent-reputation (npm),
web3-agent-reputation (PyPI), and alloy-agent-reputation (crates.io) implement the
same facts + calculator layers and pass the same golden vectors and conformance suite
(236 tests across the three languages, one shared contract). 0.2.0 adds a base rate
policy field (baseRate, the fourth term of JΓΈsang's opinion) and shouldEscalate,
a pure sufficiency/concentration gate outside the calculator β both backward-compatible
(every 0.1.0 golden vector reproduces unchanged). See CHANGELOG.md for
the full history and docs/THEORY.md Β§3.1 for the ChengβFriedman
impossibility result that bounds what those gates can promise.
web3-agents-mcp is an MCP server over the same ERC-8004 registries β the same facts, exposed as tools for an MCP-speaking agent instead of as an SDK extension. It emits facts and caveats the same way this SDK does; it does not score agents either.
MIT β see LICENSE.