<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hanjoon Choe</title>
    <description>The latest articles on DEV Community by Hanjoon Choe (@hanjoon_choe_bdd8d1f719c1).</description>
    <link>https://dev.to/hanjoon_choe_bdd8d1f719c1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4027334%2F07f753bd-78a4-4d61-b378-0940fd7052c4.png</url>
      <title>DEV Community: Hanjoon Choe</title>
      <link>https://dev.to/hanjoon_choe_bdd8d1f719c1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hanjoon_choe_bdd8d1f719c1"/>
    <language>en</language>
    <item>
      <title>We measured trust on ERC-8004 — and the naive average crowns the wrong agent</title>
      <dc:creator>Hanjoon Choe</dc:creator>
      <pubDate>Mon, 13 Jul 2026 13:45:28 +0000</pubDate>
      <link>https://dev.to/hanjoon_choe_bdd8d1f719c1/we-measured-trust-on-erc-8004-and-the-naive-average-crowns-the-wrong-agent-18gb</link>
      <guid>https://dev.to/hanjoon_choe_bdd8d1f719c1/we-measured-trust-on-erc-8004-and-the-naive-average-crowns-the-wrong-agent-18gb</guid>
      <description>&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-8004" rel="noopener noreferrer"&gt;ERC-8004 ("Trustless Agents")&lt;/a&gt; gives AI agents on-chain identity, reputation, and validation registries, now deployed across twenty-plus EVM chains. The registries store raw feedback — who rated whom, and how — and deliberately leave &lt;em&gt;scoring&lt;/em&gt; to the application layer. The community's position is explicit: a single aggregated score would be dangerous and monopolistic; the registry is a shared audit log, and an ecosystem of scorers should compete above it.&lt;/p&gt;

&lt;p&gt;We hit this question for a practical reason: AI agents are beginning to hire, pay, and delegate to other agents, and the moment before delegation needs a trust check. We wanted that check to live where developers already are — not a new service to call, but an extension of the Ethereum client you already use (viem, web3.py, alloy). Which meant we had to decide what the check should actually compute.&lt;/p&gt;

&lt;p&gt;So how should you actually score it? We pulled every feedback entry for the first ten agents registered on Base mainnet — 245 entries from 29 distinct client addresses — and tried the obvious thing first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive average lies
&lt;/h2&gt;

&lt;p&gt;Two real agents from the snapshot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Avg score&lt;/th&gt;
&lt;th&gt;Entries&lt;/th&gt;
&lt;th&gt;Distinct clients&lt;/th&gt;
&lt;th&gt;Top client's share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;#0 "Genesis Agent"&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;87.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;32%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#1 "ClawNews"&lt;/td&gt;
&lt;td&gt;70.7&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Base mainnet, blocks ≤ 47,201,455. The full snapshot ships with the SDK as a test fixture.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Rank by average and #0 wins comfortably. But look at where the evidence comes from: #0's 57 entries were filed by just eight addresses, with one address contributing eighteen of them. #1's 39 entries came from twenty independent clients. The average rewards &lt;strong&gt;volume of correlated evidence&lt;/strong&gt; over &lt;strong&gt;breadth of independent evidence&lt;/strong&gt; — precisely the failure mode reputation-systems research documented twenty years ago, now reproduced on a live chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Count evidence, don't compute scores
&lt;/h2&gt;

&lt;p&gt;The fix is older than the problem. Jøsang &amp;amp; Ismail's &lt;a href="https://www.mn.uio.no/ifi/english/people/aca/josang/publications/ji2002-bled.pdf" rel="noopener noreferrer"&gt;Beta Reputation System&lt;/a&gt; (2002) models each interaction as evidence updating a Beta posterior: accumulate positive evidence &lt;code&gt;r&lt;/code&gt; and negative evidence &lt;code&gt;s&lt;/code&gt;, and report&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# expectation (Laplace, 1774)
&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# uncertainty — a first-class output
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;b&gt;Mathematical background&lt;/b&gt; (Beta distribution, conjugacy — click to expand)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The estimation problem.&lt;/strong&gt; Model each interaction with an agent as a Bernoulli trial with unknown success probability θ ∈ [0, 1]. Reputation estimation = inferring θ from observed outcomes, while also stating how much evidence backs the inference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Beta distribution.&lt;/strong&gt; A distribution over θ itself, with parameters α, β &amp;gt; 0:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f(θ; α, β) = θ^(α−1) · (1−θ)^(β−1) / B(α, β)

mean      = α / (α + β)
variance  = αβ / ((α+β)² (α+β+1))     → shrinks as evidence grows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;α and β act as &lt;em&gt;pseudo-counts&lt;/em&gt;: α−1 successes and β−1 failures already "seen".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conjugacy — why the whole system is two counters.&lt;/strong&gt; The Beta is the conjugate prior for the Bernoulli likelihood: observing r successes and s failures updates the distribution in closed form,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Beta(α, β)  +  (r successes, s failures)  →  Beta(α + r, β + s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;No integration, no approximation — reputation state is literally just (r, s).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laplace's rule of succession (1774).&lt;/strong&gt; Start from the uniform prior Beta(1, 1) ("no idea, all θ equally likely") and the posterior mean is exactly the E above: (r+1)/(r+s+2). Zero evidence gives 0.5; evidence moves it toward the empirical rate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subjective-logic opinions.&lt;/strong&gt; Jøsang maps Beta evidence to an opinion triple (b, d, u) with b + d + u = 1:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b = r / (r+s+2)     belief
d = s / (r+s+2)     disbelief
u = 2 / (r+s+2)     uncertainty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The two operators used in this post are algebraic on this representation: &lt;em&gt;consensus&lt;/em&gt; (⊕) is evidence addition across independent witnesses; &lt;em&gt;discount&lt;/em&gt; (⊗) scales a witness's evidence by your trust c ∈ [0, 1] in that witness.&lt;/p&gt;

&lt;p&gt;Uncertainty is the part every star-rating system throws away: with no evidence, E = 0.5 and u = 1 ("we know nothing"); confidence grows only as evidence does. Subjective logic then supplies two operators — &lt;em&gt;consensus&lt;/em&gt; (fuse independent witnesses by adding evidence) and &lt;em&gt;discount&lt;/em&gt; (weight each witness by its credibility).&lt;/p&gt;

&lt;p&gt;Consensus carries a precondition, and it's the whole story: witnesses must be &lt;strong&gt;independent&lt;/strong&gt;. Fifty entries from one address are not fifty witnesses — they're one witness repeating itself. So before fusing, cap each witness's evidence mass at one unit. One witness, one voice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the correction does to real data
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Pooled (all evidence)&lt;/th&gt;
&lt;th&gt;Capped (one voice per witness)&lt;/th&gt;
&lt;th&gt;What happened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;#0 Genesis&lt;/td&gt;
&lt;td&gt;0.847 ± 0.075&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.660 ± 0.338&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;expectation falls, uncertainty &lt;strong&gt;quadruples&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#1 ClawNews&lt;/td&gt;
&lt;td&gt;0.700 ± 0.096&lt;/td&gt;
&lt;td&gt;0.665 ± 0.179&lt;/td&gt;
&lt;td&gt;barely moves&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The concentrated agent collapses — its confidence was an artifact of repetition. The broad agent is nearly invariant.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Robustness to a rule change is itself a trust signal. An agent whose score survives the independence correction earned it from many mouths.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Field notes for anyone building on 8004
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Feedback has no canonical scale.&lt;/strong&gt; The registry accepts any &lt;code&gt;value&lt;/code&gt; with any &lt;code&gt;valueDecimals&lt;/code&gt;; we measured a raw on-chain aggregate of &lt;em&gt;153.77&lt;/em&gt; on a nominal 0–100 convention. Different clients encode differently — normalize per client, or the loudest units win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Registration files verify differently by scheme.&lt;/strong&gt; &lt;code&gt;data:&lt;/code&gt; URIs are self-proving (the content lives on-chain). &lt;code&gt;ipfs://&lt;/code&gt; CIDs either check out or don't. &lt;code&gt;https://&lt;/code&gt; is unverifiable in v1 — there is no on-chain hash commitment — and honest tooling should say &lt;em&gt;unverifiable&lt;/em&gt;, never conflate it with &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;active: true&lt;/code&gt; means nothing.&lt;/strong&gt; The flag is self-declared and never expires. One prominent registered agent's advertised endpoint has been dead for weeks while its file still says active. Probe endpoints yourself; registered ≠ alive.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we shipped
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/hanjoonchoe/agent-reputation-sdk" rel="noopener noreferrer"&gt;agent-reputation-sdk&lt;/a&gt; packages this calculator with typed registry reads as native extensions to each ecosystem's canonical Ethereum SDK — &lt;a href="https://www.npmjs.com/package/agent-reputation" rel="noopener noreferrer"&gt;viem actions&lt;/a&gt; for TypeScript, a &lt;a href="https://pypi.org/project/web3-agent-reputation/" rel="noopener noreferrer"&gt;web3.py external module&lt;/a&gt; for Python, and an &lt;a href="https://crates.io/crates/alloy-agent-reputation" rel="noopener noreferrer"&gt;alloy provider trait&lt;/a&gt; for Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;agent-reputation          &lt;span class="c"&gt;# TypeScript / viem&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;web3-agent-reputation    &lt;span class="c"&gt;# Python / web3.py&lt;/span&gt;
cargo add alloy-agent-reputation     &lt;span class="c"&gt;# Rust / alloy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same API shape in every language — Python reads &lt;code&gt;w3.erc8004.get_agent_feedback(1)&lt;/code&gt; then &lt;code&gt;calculate_reputation(feedback, witness_cap=1)&lt;/code&gt;; Rust brings &lt;code&gt;Erc8004ProviderExt&lt;/code&gt; into scope and calls the same two steps on any alloy provider. Seven chains supported out of the box (Ethereum, Base, Polygon, Arbitrum, OP, BNB, Gnosis) — the chain comes from your client's RPC, the agent from its on-chain id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createPublicClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;http&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;erc8004Actions&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAgentFeedback&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateReputation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;witnessCap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// { expectation: 0.665, uncertainty: 0.179, witnesses: 20,&lt;/span&gt;
&lt;span class="c1"&gt;//   caveats: [...], policy: { ...echoed — recompute me } }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three design rules, held everywhere:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No default score exists.&lt;/strong&gt; You declare the policy (witness cap, credibility weighting), and the policy is echoed in every result — so anyone can recompute any number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never a bare scalar.&lt;/strong&gt; Results always carry uncertainty, witness statistics, and honesty caveats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Golden test vectors.&lt;/strong&gt; Raw chain snapshots are embedded as fixtures, forcing all three language implementations to produce numerically identical results — verified live: TypeScript, Python, and Rust independently returned 0.665 ± 0.179 for agent #1 against the real chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full mathematical background (Beta distribution, conjugacy, subjective logic, and the paper-to-implementation mapping) is in &lt;a href="https://github.com/hanjoonchoe/agent-reputation-sdk/blob/main/docs/THEORY.md" rel="noopener noreferrer"&gt;docs/THEORY.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't take our word for it
&lt;/h2&gt;

&lt;p&gt;Every number in this post is recomputable. The raw Base snapshot (245 entries, per-client) ships in the repo as &lt;a href="https://github.com/hanjoonchoe/agent-reputation-sdk/blob/main/vectors/base-2026-07-13.json" rel="noopener noreferrer"&gt;&lt;code&gt;vectors/base-2026-07-13.json&lt;/code&gt;&lt;/a&gt;, and each language has a runnable pre-delegation guard example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsx examples/ts/vet-agent.ts 1                                  &lt;span class="c"&gt;# TypeScript&lt;/span&gt;
uv run python examples/vet_agent.py &lt;span class="nt"&gt;--agent-id&lt;/span&gt; 1                    &lt;span class="c"&gt;# Python (packages/py)&lt;/span&gt;
cargo run &lt;span class="nt"&gt;--example&lt;/span&gt; vet_agent &lt;span class="nt"&gt;--&lt;/span&gt; 1                                  &lt;span class="c"&gt;# Rust (packages/rs)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your recomputation disagrees with ours, that's a bug — file it.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Jøsang, A. &amp;amp; Ismail, R. (2002). &lt;em&gt;The Beta Reputation System.&lt;/em&gt; 15th Bled eConference. &lt;a href="https://www.mn.uio.no/ifi/english/people/aca/josang/publications/ji2002-bled.pdf" rel="noopener noreferrer"&gt;PDF&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Jøsang, A., Ismail, R. &amp;amp; Boyd, C. (2007). &lt;em&gt;A survey of trust and reputation systems for online service provision.&lt;/em&gt; Decision Support Systems.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-8004" rel="noopener noreferrer"&gt;ERC-8004: Trustless Agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Don't ship a score. Compute your own — and let anyone verify it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Discussing this with the ERC-8004 community on &lt;a href="https://ethereum-magicians.org/t/erc-8004-trustless-agents/25098" rel="noopener noreferrer"&gt;Ethereum Magicians&lt;/a&gt; — critique welcome there or in the &lt;a href="https://github.com/hanjoonchoe/agent-reputation-sdk/issues" rel="noopener noreferrer"&gt;repo issues&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>ai</category>
      <category>rust</category>
      <category>python</category>
    </item>
  </channel>
</rss>
