Skip to main content
The AgentIdentityClient provides a TypeScript interface to the ERC-8004 agent identity standard, implemented by ag0. It handles registration, metadata management, and reputation operations.
ERC-8004 is the onchain standard for AI agent identity. Each agent receives an NFT token that carries identity, metadata, and reputation. Ownership follows the NFT — transfer the token to transfer control.

Constructor

import { AgentIdentityClient, getDefaultConfig, ChainId } from '@agether/sdk';

const identity = new AgentIdentityClient({
  config: getDefaultConfig(ChainId.Base),
  signer: yourEthersSigner,
});
The constructor takes an options object with:
  • config — an AgetherConfig object (use getDefaultConfig(ChainId.Base) for production defaults)
  • signer — an ethers.js Signer with a provider

Registration

register()

Minimal registration — mints an ERC-8004 NFT with no metadata URI. Returns the new agentId (the tokenId of the minted NFT).
const { agentId, txHash } = await identity.register();
console.log('Agent ID:', agentId.toString());
console.log('TX:', txHash);

registerWithURI(agentURI)

Register with an IPFS or HTTP metadata URI. The URI should point to a JSON document describing the agent.
const { agentId, txHash } = await identity.registerWithURI(
  'ipfs://QmYourAgentMetadata'
);

registerWithMetadata(uri, metadata[])

Register with both a URI and onchain key-value metadata.
const { agentId, txHash } = await identity.registerWithMetadata(
  'ipfs://QmYourMetadata',
  [
    { key: 'name', value: 'MyLendingAgent' },
    { key: 'version', value: '1.0.0' },
    { key: 'capabilities', value: 'lending,borrowing' },
  ]
);

registerOrGet()

Register only if the wallet doesn’t already own an ERC-8004 identity. Throws an error if the wallet already has one — use hasExistingIdentity() to check first.
try {
  const { agentId, existing } = await identity.registerOrGet();
  console.log('Newly registered:', agentId.toString());
} catch (e) {
  console.log('Wallet already has an identity. Use agether init <pk> --agent-id <id>');
}
registerOrGet() throws if an identity already exists. It does not return the existing agentId — you need to know your agentId separately (e.g., from the registration transaction or via ERC-721 enumeration).

hasExistingIdentity()

Check whether the wallet already owns an ERC-8004 token.
const exists = await identity.hasExistingIdentity();

Metadata

getAgentURI(agentId)

Read the agent’s metadata URI from the registry.
const uri = await identity.getAgentURI(agentId);
console.log('Agent URI:', uri); // "ipfs://..."

setAgentURI(agentId, newURI)

Update the agent’s metadata URI.
const txHash = await identity.setAgentURI(agentId, 'ipfs://QmNewMetadata');

setMetadata(agentId, key, value)

Set an individual onchain metadata key-value pair.
await identity.setMetadata(agentId, 'name', 'UpdatedAgentName');
await identity.setMetadata(agentId, 'version', '2.0.0');

getMetadata(agentId, key)

Read an onchain metadata value.
const name = await identity.getMetadata(agentId, 'name');
const version = await identity.getMetadata(agentId, 'version');

fetchAgentMetadata(agentId)

Fetch and parse the agent’s JSON metadata from its URI (handles IPFS URIs).
const metadata = await identity.fetchAgentMetadata(agentId);
if (metadata) {
  console.log('Name:', metadata.name);
  console.log('Description:', metadata.description);
}

transfer(agentId, to)

Transfer the agent identity NFT to a new owner. This also transfers control of the Safe account.
const txHash = await identity.transfer(agentId, '0xNewOwner...');

Reputation

The reputation functions interact with the ERC-8004 Reputation Registry (currently deployed on Sepolia; Base deployment pending).

giveFeedback(input)

Publish a feedback signal to the ERC-8004 Reputation Registry.
const txHash = await identity.giveFeedback({
  agentId: 17676n,
  value: 10,          // -128 to 127 (int128)
  decimals: 0,        // optional, default 0
  tag1: 'credit',     // category
  tag2: 'repayment',  // specific tag
  endpoint: '',       // optional
  feedbackURI: '',    // optional
});

getReputation(agentId, tag1?, tag2?)

Read the aggregated reputation summary for an agent.
const reputation = await identity.getReputation(agentId);
console.log('Total feedback count:', reputation.count);
console.log('Total value:', reputation.totalValue);
console.log('Average value:', reputation.averageValue);
console.log('Clients:', reputation.clients);
Return type:
interface ReputationSummary {
  count: number;
  totalValue: number;
  averageValue: number;
  clients: string[];
}

verifyForCredit(agentId)

Check if an agent is eligible for Agether credit (exists in registry + no negative credit reputation).
const result = await identity.verifyForCredit(agentId);
console.log('Eligible:', result.eligible);
if (!result.eligible) {
  console.log('Reason:', result.reason);
}

ERC-8004 Contract Addresses

NetworkChain IDIdentity RegistryReputation Registry
Base84530x8004A169FB4a3325136EB29fA0ceB6D2e539a432— (pending deployment)
Sepolia111551110x8004A818BFB912233c491871b3d84c89A494BD9e0x8004B663056A597Dffe9eCcC1965A193B7388713

ERC-8004 Reputation Mapping

Agether’s Agether8004Scorer contract maps credit scores to ERC-8004 feedback values:
Credit ScoreFeedback ValueMeaning
≥ 700+10Good credit
≥ 500+5Neutral-good
≥ 400-5Neutral-bad
< 400-10Bad credit

Complete Example

import { AgentIdentityClient, getDefaultConfig, ChainId } from '@agether/sdk';
import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('https://base-rpc.publicnode.com');
const signer = new ethers.Wallet(process.env.AGENT_PRIVATE_KEY!, provider);

const identity = new AgentIdentityClient({
  config: getDefaultConfig(ChainId.Base),
  signer,
});

// Check if wallet already has an identity
const hasIdentity = await identity.hasExistingIdentity();

if (!hasIdentity) {
  // Register with metadata
  const { agentId, txHash } = await identity.registerWithMetadata(
    'ipfs://QmAgentMetadata',
    [
      { key: 'name', value: 'CreditBot' },
      { key: 'purpose', value: 'autonomous-lending' },
    ]
  );
  console.log('Agent ID:', agentId.toString());
  console.log('TX:', txHash);
}
The AgentIdentityClient is used internally by MorphoClient during registration. You only need to use it directly if you want fine-grained control over identity, metadata, and reputation.