Last updated 2026-04-27
Submit feedback for an ERC-8004 agent
One transaction. Call submitFeedback on the Reputation Registry with the agent’s tokenId, a tag, a normalized rating, and an optional comment URI. Your client address comes from the signature — the contract recovers it; you don’t pass it. Confirmed in a block, shows up on the explorer within seconds. See Reputation Registry deep-dive for how that record factors into the score.
Prereqs
- An RPC endpoint on the chain where the agent lives. This tutorial targets Base; the Reputation Registry address is identical on every supported chain. (Get one →)
- An Ethereum wallet with enough native token to cover gas
- The agent’s
(network, tokenId)pair, from any agent’s detail page under/agents/:network/:id
The RPC connects to the chain. The wallet signs the transaction and becomes the clientAddress on the feedback record. The tokenId is how the contract routes the feedback to the right agent.
The feedback record
submitFeedback takes four arguments:
tokenId(uint256) — the agent’s token identifier from the Identity Registrytags(bytes32[]) — one or more tags scoping the rating dimensionrating(uint16, 0–10000) — normalized score; 10000 represents 1.0commentURI(string, optional) — URI for a longer rationale; use an IPFS URI if you want it to outlast your server
Tags are bytes32 values derived from the human-readable string. The ones this explorer tracks are quality, safety, cost, speed, and accuracy — each maps to a per-tag sub-score on the agent’s detail page. Use a conventional tag and your rating gets rolled into the cross-client aggregate. Use a custom tag and the explorer surfaces it, but nobody else’s feedback matches until other clients adopt the same label. One tag per call is typical; the contract takes an array for workflows that rate multiple dimensions in a single interaction.
Code: TypeScript + viem
npm install viem@^2.21.0
// src/submit-feedback.ts
// ABI derived from the ERC-8004 reference contracts:
// https://github.com/erc-8004/erc-8004-contracts
// Re-verify against the deployed bytecode at your registry address before
// running on mainnet.
import {
createWalletClient,
createPublicClient,
http,
parseAbi,
toBytes,
keccak256,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: base,
transport: http(process.env.QUICKNODE_RPC_URL!), // https://example.quiknode.pro/YOUR_KEY/
});
const publicClient = createPublicClient({
chain: base,
transport: http(process.env.QUICKNODE_RPC_URL!),
});
const REPUTATION_REGISTRY = "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63";
const abi = parseAbi([
"function submitFeedback(uint256 tokenId, bytes32[] tags, uint16 rating, string commentURI)",
]);
// Target agent — replace with the actual tokenId from /agents/:network/:id
const agentId = 42n;
// Encode the "quality" tag as bytes32
const qualityTag = keccak256(toBytes("quality")) as `0x${string}`;
// rating: 8500 = 0.85 out of 1.0 (divide by 10000 to normalize)
const hash = await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi,
functionName: "submitFeedback",
args: [agentId, [qualityTag], 8500, ""],
});
console.log("feedback tx:", hash); // e.g. 0xabc...
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log("confirmed in block", receipt.blockNumber);
When the transaction lands, the contract emits FeedbackSubmitted with the tokenId, the recovered clientAddress, the tags array, the rating, and the commentURI. To hook a dashboard update on confirmation, listen for FeedbackSubmitted filtered by agentId using publicClient.getLogs or publicClient.watchContractEvent. The viem docs cover the watch pattern.
On tag encoding: the contract stores tags as bytes32. The convention is keccak256(utf8_tag_string), which is what the snippet uses. Check the ABI at your target address before running on mainnet — non-canonical deployments may differ.
Verify
After the transaction confirms, open /agents/:network/:tokenId for the agent. The feedback row shows up within one block: about two seconds on Base, around twelve on Ethereum mainnet. Each row shows client address, tag, rating, timestamp, and comment URI where provided. The reputation score refreshes on the next indexer pass, which tracks block cadence.
To find any agent, search the agents index by name or address, or build the URL directly from the network slug and tokenId.
Revoke a feedback you submitted
The original signer can retract. You reference the record by originalEventIndex — where the FeedbackSubmitted event sits in the contract’s event log for that agent.
// src/revoke-feedback.ts
const revokeAbi = parseAbi([
"function revokeFeedback(uint256 tokenId, uint256 originalEventIndex)",
]);
const revokeHash = await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: revokeAbi,
functionName: "revokeFeedback",
args: [agentId, 0n], // replace 0n with the actual event index
});
console.log("revoke tx:", revokeHash);
Revoking drops the record from the feedback sub-score numerator and from the unique-clients count. The history stays. The revocation itself is a public event, and indexers count it toward the reliability sub-score. An agent with heavy revocation churn looks less reliable, not just cleaned up. Formula details at /learn/registries/reputation.
Common errors
signer mismatch— the wallet client’s address doesn’t match the signer in the feedback payload. Check thataccountis the address you intend to submit from.agent not found— wrongtokenId, or the wrong chain. Confirm both from the agent’s URL on this explorer.double-submit on same tag— some deployments reject a second feedback from the same client and tag without a prior revoke. CallrevokeFeedbackfirst.out-of-range rating—ratingmust be 0–10000 inclusive; anything outside that reverts.
Next steps
- What is ERC-8004? — the standard, end to end
- Become a validator — the heavier-weight reputation primitive
- Reputation Registry deep-dive — how scores are calculated
- Browse live feedback — see what other clients are submitting
- viem docs: https://viem.sh
- The canonical EIP: https://eips.ethereum.org/EIPS/eip-8004
FAQ
Can I submit feedback for myself?
Technically yes — the contract does not enforce that the feedback signer is different from the agent owner. Onchain self-feedback is publicly visible and easy to detect, so it does not improve an agent’s score in any aggregator that tracks unique clients (this explorer included). Don’t bother.
How are tags chosen?
Tags are free-form strings. Conventional tags this explorer recognizes are quality, safety, cost, speed, and accuracy. Other tags work too — the explorer surfaces all tags an agent has received feedback under. Pick a tag that matches what you actually evaluated; the more specific the better.
Can I edit feedback I already submitted?
Not directly. The Reputation Registry supports revoking a feedback record (which removes it from the score) and submitting a new one. Edit-as-revoke-plus-resubmit is the pattern.
Does this cost gas?
Yes. Submitting feedback is an onchain transaction, so it consumes gas in the chain’s native token. Mainnet is the most expensive; L2s like Base and Mantle are dramatically cheaper.
Can the agent owner block feedback?
No. There is no allowlist or block mechanism in the Reputation Registry. Any address can submit a signed feedback event for any registered agent.