azeth_get_weighted_reputation
Check an agent's on-chain reputation using USD-weighted ratings to assess trustworthiness before interactions. Returns weighted average based on rater payments.
Instructions
Get USD-weighted reputation for an agent from the on-chain ReputationModule.
Use this when: You want to check the reputation of an agent or service before interacting. Returns a weighted average where each rater's influence is proportional to their USD payment to the agent.
Returns: Weighted reputation with weightedValue (int256), totalWeight, and opinionCount.
Note: This is a read-only on-chain query. No private key or gas is required. Leave raters empty to aggregate across all raters who have submitted opinions.
Example: { "agentId": "1024" } or { "agentId": "1024", "raters": ["0x1234...abcd"] }
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chain | No | Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet"). | |
| agentId | Yes | Target agent's ERC-8004 token ID (numeric string). | |
| raters | No | Specific rater addresses to include (optional). Empty = all raters. |
Implementation Reference
- src/tools/reputation.ts:143-241 (handler)The asynchronous handler function that executes the azeth_get_weighted_reputation tool, interacting with the ReputationModule contract via viem.
async (args) => { const agentIdCheck = validateUint256(args.agentId, 'agentId'); if (!agentIdCheck.valid) { return error('INVALID_INPUT', `${agentIdCheck.fieldName} exceeds maximum uint256 value`); } try { const { createPublicClient, http } = await import('viem'); const resolved = resolveChain(args.chain); const chain = resolveViemChain(resolved); const rpcUrl = process.env[RPC_ENV_KEYS[resolved]] ?? SUPPORTED_CHAINS[resolved].rpcDefault; const publicClient = createPublicClient({ chain, transport: http(rpcUrl), }); const moduleAddress = AZETH_CONTRACTS[resolved].reputationModule; if (!moduleAddress || moduleAddress === ('' as `0x${string}`)) { return error('NETWORK_ERROR', `ReputationModule not deployed on ${resolved}.`, 'Deploy the ReputationModule first or switch to baseSepolia.'); } // Check if the token ID exists on the trust registry before querying reputation const trustRegistryAddr = AZETH_CONTRACTS[resolved].trustRegistryModule; if (trustRegistryAddr && trustRegistryAddr !== ('' as `0x${string}`)) { try { const accountAddr = await publicClient.readContract({ address: trustRegistryAddr, abi: TrustRegistryModuleAbi, functionName: 'getAccountByTokenId', args: [agentIdCheck.bigint], }); if (accountAddr === '0x0000000000000000000000000000000000000000') { return success({ agentId: args.agentId, weightedValue: '0', totalWeight: '0', opinionCount: '0', warning: `No agent registered with token ID ${args.agentId}. The returned zeros indicate no registration, not a zero reputation.`, }); } } catch { // getAccountByTokenId may not exist on older deployments — proceed with query } } const raterAddrs = args.raters .filter((a): a is `0x${string}` => /^0x[0-9a-fA-F]{40}$/.test(a)); let result: readonly [bigint, bigint, bigint]; if (raterAddrs.length > 0) { result = await publicClient.readContract({ address: moduleAddress, abi: ReputationModuleAbi, functionName: 'getWeightedReputation', args: [agentIdCheck.bigint, raterAddrs], }) as readonly [bigint, bigint, bigint]; } else { result = await publicClient.readContract({ address: moduleAddress, abi: ReputationModuleAbi, functionName: 'getWeightedReputationAll', args: [agentIdCheck.bigint], }) as readonly [bigint, bigint, bigint]; } const [weightedValue, totalWeight, opinionCount] = result; // Format weighted value: the contract returns values in the same decimal precision // as the submitted opinions. For the default MCP submission (valueDecimals=0), this // is an integer. For SDK submissions with 18 decimals, format accordingly. // Heuristic: if |value| > 10^15, it's likely 18-decimal; otherwise treat as integer. const absValue = weightedValue < 0n ? -weightedValue : weightedValue; const isHighPrecision = absValue > 10n ** 15n; const weightedValueFormatted = isHighPrecision ? formatTokenAmount(weightedValue, 18, 4) : weightedValue.toString(); // totalWeight is a dampened dimensionless value: sum of pow2over3(netPaidUSD) across raters. // It is NOT USD — do not format as currency. Display as a plain number. const totalWeightFormatted = formatTokenAmount(totalWeight, 12, 2); return success({ agentId: args.agentId, weightedValue: weightedValue.toString(), weightedValueFormatted, totalWeight: totalWeight.toString(), totalWeightFormatted, totalWeightDescription: 'Aggregate economic skin-in-the-game (higher = more payments behind opinions)', opinionCount: opinionCount.toString(), ratersFilter: raterAddrs.length > 0 ? raterAddrs : '(all raters)', }); } catch (err) { return handleError(err); } }, ); - src/tools/reputation.ts:132-142 (schema)Input validation schema for azeth_get_weighted_reputation tool.
inputSchema: z.object({ chain: z.string().optional().describe('Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet").'), agentId: z.string().regex(/^\d+$/, 'Must be a non-negative integer string').describe('Target agent\'s ERC-8004 token ID (numeric string).'), raters: z.preprocess( (val) => typeof val === 'string' ? JSON.parse(val) : val, z.array( z.string().regex(/^0x[0-9a-fA-F]{40}$/, 'Each rater must be a valid Ethereum address'), ).default([]), ).describe('Specific rater addresses to include (optional). Empty = all raters.'), }), }, - src/tools/reputation.ts:116-142 (registration)Registration of the azeth_get_weighted_reputation tool with the server.
server.registerTool( 'azeth_get_weighted_reputation', { description: [ 'Get USD-weighted reputation for an agent from the on-chain ReputationModule.', '', 'Use this when: You want to check the reputation of an agent or service before interacting.', 'Returns a weighted average where each rater\'s influence is proportional to their USD payment to the agent.', '', 'Returns: Weighted reputation with weightedValue (int256), totalWeight, and opinionCount.', '', 'Note: This is a read-only on-chain query. No private key or gas is required.', 'Leave raters empty to aggregate across all raters who have submitted opinions.', '', 'Example: { "agentId": "1024" } or { "agentId": "1024", "raters": ["0x1234...abcd"] }', ].join('\n'), inputSchema: z.object({ chain: z.string().optional().describe('Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet").'), agentId: z.string().regex(/^\d+$/, 'Must be a non-negative integer string').describe('Target agent\'s ERC-8004 token ID (numeric string).'), raters: z.preprocess( (val) => typeof val === 'string' ? JSON.parse(val) : val, z.array( z.string().regex(/^0x[0-9a-fA-F]{40}$/, 'Each rater must be a valid Ethereum address'), ).default([]), ).describe('Specific rater addresses to include (optional). Empty = all raters.'), }), },