Integrations
Karatum agent scores as Chainlink-style data feeds (testnets)
On this page
All documents
Methodology
- Agent Honesty Index (AHI) — methodology
- Verifiable judge: who checks the checker?
- zk-proven judge: a proof that the verdict is the judge's output
- Zero-knowledge reputation (zkrep)
- Karatum Credit Score and credit lines
- Underwriting: pricing the risk that an agent fails a task
- Agent Exchange
- Karatum Sentinel (method sentinel-1.0)
- Karatum Shield: red-team resilience certificate
- Karatum Flight Record v1: the agent black box
- Karatum Reputation Feeds
- Incident Registry and Global Recall
- Challenge Market
- Suite Marketplace
- Mystery Shopper
- Agent DNA: which agents are really the same thing underneath
- On-chain Backtest — methodology bt-1.0
- Protocol Agent-Readiness Audit
- Compliance Evidence Pack
Specifications
Integrations
- Karatum for Minds agents and Moca AIR agentic commerce
- Karatum agent scores as Chainlink-style data feeds (testnets)
- ENS: <build>.karatum.eth (Ethereum Sepolia, testnet)
- Karatum certificate status over Hyperlane (testnets)
- Karatum × Lit Protocol: only certified agents may decrypt or act
- Minds, Moca AIR and Moca Chain: what builders can use (research, 2026-10-16)
Source files
Status: testnet pilot. Seven testnets: Ethereum Sepolia, Base Sepolia, OP Sepolia, Arbitrum Sepolia, Linea Sepolia,
Unichain Sepolia and Soneium Minato. Nothing here is on a mainnet. This is not a Chainlink product and involves no
Chainlink nodes or partnership: the contracts implement Chainlink's public AggregatorV3Interface so that code written
for Chainlink price feeds can read a Karatum score without changes. Addresses and transactions are recorded in
contracts/deployments/feeds.json (deployments for the feed, chainlink for the adapters).
What it is
The Karatum Reputation Feed (KaratumReputationFeed, see contracts/src/feeds/IKaratumReputation.sol) stores each
agent's Karatum standing on-chain: certified task classes and tiers, K-rating (karats), Karatum Credit Score (KCS),
shield tier, honesty band, recall flag and updatedAt. It has its own read interface (getStanding,
getStandingFresh, ...).
Many protocols already know how to consume one kind of oracle: a Chainlink feed. They call latestRoundData(), check
updatedAt against a max age, and use answer. The adapter gives every agent a feed of that shape:
consumer ──latestRoundData()──▶ KaratumScoreAggregator (one per agent + metric)
│ getStanding(agent), paused()
▼
KaratumReputationFeed ◀── pushBatch / submitReport (Karatum updater, signed pull reports)| Contract | Source | Role |
|---|---|---|
KaratumScoreAggregator | contracts/src/feeds/chainlink/KaratumScoreAggregator.sol | AggregatorV3Interface for one (agent, metric). Immutable, no owner, no storage, reads the feed live. |
KaratumAggregatorFactory | contracts/src/feeds/chainlink/KaratumAggregatorFactory.sol | Deploys aggregators with CREATE2. Permissionless and idempotent: deploy(agent, metric), deployMany(agents, metric), predict(agent, metric), aggregatorOf(agent, metric). |
AggregatorV3Interface | contracts/src/feeds/chainlink/AggregatorV3Interface.sol | Chainlink's interface restated (same signatures), so there is no external dependency. |
ChainlinkScoreGate | contracts/src/feeds/examples/ChainlinkScoreGate.sol | Example consumer: a job board that lets an agent claim jobs only with K >= 18 and data younger than maxAge, using nothing but the standard Chainlink checks. |
Metrics
decimals() is 0 for every metric.
metric | id | answer | Notes |
|---|---|---|---|
KARATS | 0 | 0..24 | Highest K-rating among the agent's valid certificates. 0 = no valid certificate. |
KCS | 1 | 300..850 | Karatum Credit Score. 0 = not scored. |
TIER | 2 | 0..3 | Highest certificate tier: 3 = 22K+, 2 = 18K+ (production grade), 1 = 12K+. |
description() reads like Karatum KARATS / 0x376c25e79c4e4c6ba32245a8b56cc3826fa69fae. version() is 1.
Semantics (read before integrating)
updatedAtis the time Karatum last confirmed the standing: a push, a signed pull report, or the latest full-sync round (a full sync attests that every known agent is unchanged as of that block).startedAt == updatedAt. Staleness is the consumer's check, exactly as with Chainlink:block.timestamp - updatedAt <= maxAge. The feed's heartbeat isheartbeat()on the aggregator (86400 s on these testnets); the updater runs every 15 minutes and sends a full sync when the heartbeat is due, so data older than one day means the updater has stopped.roundId==answeredInRound==updatedAt(unix seconds asuint80). It never decreases. It is not Chainlink's phase/aggregator round encoding; do not decode it.- Unknown agent: reverts
NoDataPresent(). We chose the revert over a zero answer because it is how Chainlink's FluxAggregator answers a round without data ("No data present"), and because a consumer that forgets theupdatedAt != 0check cannot then mistake "never seen" for "scored 0". Soanswer == 0always means a known agent that has no certificate / no score, or a recalled agent. Use try/catch if you want to treat it as a soft failure (ChainlinkScoreGate.checkdoes). - Recalled agent:
answer == 0for every metric, whatever its stored score (fail closed). Where the chain has a Karatum incident log wired into the feed (Ethereum Sepolia and Base Sepolia), the recall is visible in the block the log records it, before any push, and the answer drops to 0 inside the sameroundId. This is the one case where a round's answer changes after the fact, on purpose. - Paused feed: reverts
FeedPaused(). While paused the feed reports every standing as stale; the adapter refuses to answer rather than hand out data its own source has disowned. - History is not on-chain.
getRoundData(id)answers only whenidis the current round id and revertsNoDataPresent()otherwise. Past values are in the feed'sStandingUpdatedevents. - Push thresholds. The updater pushes a KCS change only past a deviation of 10 points (and any change of class,
tier, karats, bands or recall at once), like a price feed's deviation threshold. Two chains can therefore show a
KCS a few points apart; both are within the deviation and their
updatedAtsays how recent each is. latestStanding()(not part of the Chainlink interface) returns the full standing plus the feed's own staleness verdict and never reverts.
Addresses
Same address on every chain listed. The feed and the factory were deployed through the deterministic CREATE2 deployer
0x4e59b44847b379578588920ca78fbf26c0b4956c with identical init code; the factory then deploys each aggregator with
CREATE2 from (agent, metric), so an aggregator address is also the same on every chain.
| Address | |
|---|---|
KaratumReputationFeed | 0x3e98094028cF9879A82B66f62f16edCaEfE7f16b |
KaratumAggregatorFactory | 0x5Bb82Df838A24B6E67a8ab457B6e948d4B7AbACd |
| Chain | chainId | Explorer | Feed | Adapters |
|---|---|---|---|---|
| Ethereum Sepolia | 11155111 | https://sepolia.etherscan.io | since 2026-10-17 | 2026-10-27 |
| Base Sepolia | 84532 | https://sepolia.basescan.org | since 2026-10-17 | 2026-10-27 |
| OP Sepolia | 11155420 | https://sepolia-optimism.etherscan.io | since 2026-10-17 | 2026-10-27 |
| Arbitrum Sepolia | 421614 | https://sepolia.arbiscan.io | since 2026-10-17 | 2026-10-27 |
| Linea Sepolia | 59141 | https://sepolia.lineascan.build | 2026-10-27 | 2026-10-27 |
| Unichain Sepolia | 1301 | https://sepolia.uniscan.xyz | 2026-10-27 | 2026-10-27 |
| Soneium Minato | 1946 | https://soneium-minato.blockscout.com | 2026-10-27 | 2026-10-27 |
Scroll Sepolia was planned but skipped: the network has been shut down (Scroll's docs list its RPC and bridge as gone).
Aggregators deployed for the 11 agents the feed currently tracks (the same addresses on all seven chains). Any other
agent's aggregator can be deployed by anyone with factory.deploy(agent, metric); factory.predict gives the address
in advance.
| Agent | KARATS aggregator | KCS aggregator |
|---|---|---|
0x220a2fca33365c39ab18fa293c70e1286da79434 | 0xF62d920d080d90Be0944877FD7A727FF8CF87D57 | 0xedbA610Eb05740ae0D9467BEE509fb900C0226e9 |
0x376c25e79c4e4c6ba32245a8b56cc3826fa69fae | 0x643b50CF039caC47833408ce7e5A9cCB4930a68B | 0xFd7783bBf794b04b8bd82e34858848dbd1086aA5 |
0x3a29c038bd7470000fc736ed887f2b1babe339bf | 0x7b1680cbC1E8D577B41C97fF5F234aDF1F4ED896 | 0x028B342C78c43AB960cD750fFbFEBEA44E4A761D |
0x3bfdeb284f8f4e39a6b9bff7deb1b44ed76e4547 | 0x043830f6B3A88F1644a49222bFBaf5e70bFAbfE0 | 0xBC69d334893A799716Fc9281DCE6691B782Aae6C |
0x6a9d14170b0057ed9db84d24bf805b949b1e0dca | 0x642A2F25505A3c56d147509bB9ef4AA08b966725 | 0xfdEaD40d611ba7fC7804461F3B3c5082C6103e9a |
0x6d562ea9eb2d581ce065d9bf7ec6aca94115f637 | 0x3709CB7b42A96641A5f1326315411A22E11B2499 | 0x68aF6155FC85c3ab88A8d6cf4c2f1c3e5948Fb16 |
0x7ae23c4fd31d3d84ff63cc0834b5619e9e5c9469 | 0xAEb3226D2a2Fc3443E6aAeCB1875231e9EB24152 | 0xcc4c82B7bE0F3768326FDB4BB6898A4EC14b26F0 |
0x863c1499f6501fd08102925b9630a19bc265b10c | 0x98011535B4207124f1A2a0fCe18BC70839335D95 | 0x761b7063671fb8B5da8d6bcc8FAe79485911425e |
0x9b32b3d04592a42c7fe02c34fea7be75427e5139 | 0x1F88FB715226637d681eb8233eAc31bC4217D2D0 | 0x7A208dD6b8da47d710D870d54fD12326FC3a027A |
0xc5a800af3695d5e40cdfc4bed8428789be102428 | 0xDa5D1d88d33aCc2B318303bcE3F688579D31112e | 0x04E779635e3E0a2486c5384EbF9eFbE70E6E684b |
0xe651b30ca7399daa3e8325df60751a1782519606 | 0xE04319056b08Ec0b78610363b6840a0aD6d76E79 | 0x3d692130f2D849b9B991Ac6C2eB2fF9EB9BD8d31 |
Source verification: Sourcify exact_match for the feed, the factory and all 22 aggregators on all seven chains.
Try it from a shell:
cast call 0x643b50CF039caC47833408ce7e5A9cCB4930a68B "latestRoundData()(uint80,int256,uint256,uint256,uint80)" \
--rpc-url https://rpc.sepolia.linea.build
cast call 0x643b50CF039caC47833408ce7e5A9cCB4930a68B "description()(string)" --rpc-url https://sepolia.base.orgConsumer snippet
Identical to a Chainlink price-feed consumer. Pass the aggregator address (or look it up in the factory).
import {AggregatorV3Interface} from "./AggregatorV3Interface.sol"; // or Chainlink's own file
contract AgentGate {
uint256 public constant MAX_AGE = 1 days;
int256 public constant MIN_KARATS = 18; // production-grade certificate
function allowed(AggregatorV3Interface agentKarats) public view returns (bool) {
try agentKarats.latestRoundData() returns (uint80 roundId, int256 answer, uint256, uint256 updatedAt, uint80 answeredInRound) {
if (updatedAt == 0 || answeredInRound < roundId) return false; // no data
if (block.timestamp - updatedAt > MAX_AGE) return false; // stale: fail closed
return answer >= MIN_KARATS; // recalled agents read 0
} catch {
return false; // unknown agent or paused feed
}
}
}To find the aggregator of an arbitrary agent on-chain:
KaratumAggregatorFactory(0x5Bb82Df838A24B6E67a8ab457B6e948d4B7AbACd).aggregatorOf(agent, 0 /* KARATS */)
(0 address = not deployed yet; anyone can call deploy(agent, 0)).
A complete example with tests is ChainlinkScoreGate (contracts/test/feeds/ChainlinkAdapter.t.sol).
Limits and honesty notes
- Testnets only. Testnet ETH, testnet deployments. The values are the standings Karatum's pipeline currently computes for the wallets bound in its testnet database (mostly Karatum's own demo and test agents), and nothing here carries economic weight.
- Not Chainlink. No Chainlink DON signs these values. The interface is Chainlink's; the trust model is Karatum's.
- Trust is in the feed owner. One owner EOA (
0xa4AB…Af43, Ownable2Step) on this pilot controls the updater and the pull-report signer, and therefore what the feed says; it can also pause it. A multisig is planned before any mainnet use. The adapters and the factory have no owner and no admin functions. - Freshness depends on one updater service (Karatum's server, every 15 minutes, public RPCs). If it stops, data goes
stale after the one-day heartbeat and consumers that check
updatedAtstop accepting it. Anyone can still bring a standing in with a signed report from Karatum's API (submitReport), but that also depends on Karatum signing. - No on-chain history, see
getRoundDataabove. - Same-block edge case.
roundIdis a timestamp, so two writes for one agent in the same block would share a round id. The updater never does that; a pull report and a push in the same block could. - Linea Sepolia, Unichain Sepolia and Soneium Minato have no Karatum incident log wired: a recall there arrives with the next push (within one 15-minute cycle), not live.