Reputation Model
An agent's reputation is a single number from 0 to 100. It is the sum of six factors, each capped, each earned from a different real-world signal. Nothing about it is subjective or hand-assigned: the oracle recomputes every factor from observable data each epoch, proposes the result to the CountersigReputation contract, and after a challenge window it becomes the on-chain score anyone can read in one call. The point of the breakdown below is that a score is never a black box — you can always see which factors produced it.
Where each signal comes from
This is the part that matters: a factor only moves when something real happens.
- Success Rate & Fee Activity come from attestations — a consuming platform reports, per completed job, whether the agent succeeded or failed. CounterAudit does this today: every audited agent action it seals feeds a success/failure signal to the oracle. More successful work → higher score. An agent with no work history earns 0 on both.
- Registration Age comes from the clock — how long ago the agent registered on-chain. It grows logarithmically, so it rewards genuine longevity but a fresh identity cannot fake it.
- Community Verification comes from flags — watchdog services (e.g. rug-scanners on the same chain) report misbehaving agents to the oracle. Flags subtract from this factor.
- External Trust is live via ERC-8004. An agent that links its Countersig identity to an ERC-8004 agent it owns gets an external-trust score computed from that agent's on-chain feedback — the oracle normalizes the recognized rating dimensions and excludes ones it can't interpret. Unlinked agents score 0 here.
- Trust Propagation (an agent-vouching graph) is not yet active and contributes 0 for every agent.
So on testnet today, a live score is driven by success attestations, age, flags, and ERC-8004 external trust. A brand-new agent with no work sits near the community baseline (5) and climbs only as real activity accrues — which is exactly why the number means something.
The 6 Factors
| Factor | Max | Formula (live oracle) | Status |
|---|---|---|---|
| feeScore | 30 | min(30, floor(attestations / 10)) | live |
| successScore | 25 | floor((successful / total) × 25) | live |
| ageScore | 20 | min(20, floor(log₂(days + 1) × 4)) — reaches 20 at day 31 | live |
| externalScore | 15 | Normalized ERC-8004 feedback (linked agents) | live |
| communityScore | 5 | max(0, 5 − flags × 2) | live |
| propagationScore | 5 | agent-vouching trust graph | Phase 2 |
Only propagationScore is still inactive (0 today), so a live score currently maxes at 95 (30+25+20+15+5). externalScore is 0 unless the agent links an ERC-8004 identity it owns. You can see any agent's live per-factor breakdown on the App page.
Sybil Resistance
The algorithm is designed so that creating fake identities to farm reputation is economically irrational. A brand-new agent cannot score above 5 (community baseline) without sustained economic activity over time. The logarithmic age formula front-loads rewards for early legitimate registrations while making rapid score accumulation impossible for freshly created Sybil identities.
Oracle Epochs
The oracle runs on an epoch cycle (hourly on testnet; a longer cadence in production). Each epoch it gathers the signals above for every registered agent, computes the 6-factor score, and calls proposeReputation(didHash, ReputationData) on the CountersigReputation contract, which rejects any factor above its cap. A proposed score sits through a challenge window (rejectable by the slashing committee) before anyone can permissionlessly call finalizeReputation(didHash) to make it the live on-chain value. This propose-then-finalize design means a bad score can be contested before it takes effect, and no single oracle write is trusted blindly.
Reading a Score On-Chain
// Solidity — gate a function on minimum reputation
interface ICountersigReputation {
function meetsThreshold(bytes32 didHash, uint8 threshold) external view returns (bool);
function getTotalScore(bytes32 didHash) external view returns (uint8);
}
contract TrustedAgentGate {
ICountersigReputation public reputation;
uint8 public minScore = 60;
modifier onlyTrustedAgent(bytes32 agentDidHash) {
require(reputation.meetsThreshold(agentDidHash, minScore), "Insufficient reputation");
_;
}
}
Reading a Score via SDK
const verifier = new CountersigVerifier({ rpcUrl, addresses, chainId: 46630 });
// Get full breakdown
const rep = await verifier.getReputation(agentDid);
console.log(rep.total); // 0–100
console.log(rep.feeScore); // 0–30
console.log(rep.ageScore); // 0–20
// Simple threshold check (no gas)
const trusted = await verifier.meetsThreshold(agentDid, 60);
Score Trust Tiers
| Score Range | Label | Meaning |
|---|---|---|
| 80–100 | HIGH | Established, trusted agent with sustained economic activity |
| 60–79 | MEDIUM | Verified agent with moderate history |
| 40–59 | LOW | New or limited activity agent |
| 0–39 | UNVERIFIED | Insufficient data, new registration, or flagged |
Slashing and Score Reset
When an agent is slashed via CountersigStaking.executeSlash(), the staking contract calls zeroReputation(didHash) on the reputation contract. All six factor scores are set to zero. The agent's identity status is permanently set to Slashed — it cannot be reinstated or re-registered at the same address. Historical audit records sealed before the slash retain the reputation score at the time of the action; the slash does not rewrite history.