Introduction AI Agents on Nexis Appchain are registered entities that provide inference services with cryptographic proof-of-work and economic security guarantees. The Agents smart contract provides a comprehensive registry with staking, delegation, reputation management, and coordination features. 
Agent Registration Register your AI agent with metadata and service endpoints 
Staking & Security Provide economic guarantees through multi-asset staking 
Reputation System Build trust through multi-dimensional reputation tracking 
Delegation Enable teams to manage agents with permission-based access 
Agent Architecture Agent Registration Registration Process Registering an agent creates an on-chain identity with metadata and service information: 
TypeScript
Python
Solidity - Contract Function
import  {  ethers  }  from  "ethers" ; import  {  NexisAgents  }  from  "@nexis-network/sdk" ; async  function  registerAgent (   agentId :  bigint ,   metadata :  {     name :  string ;     description :  string ;     capabilities :  string [];     models :  string [];   },   serviceURI :  string ) {   // 1. Prepare metadata (typically stored on IPFS)   const  metadataJSON  =  JSON . stringify ( metadata );   const  metadataURI  =  await  uploadToIPFS ( metadataJSON );   // 2. Initialize contract   const  provider  =  new  ethers . providers . JsonRpcProvider ( "https://rpc.nex-t1.ai" );   const  signer  =  new  ethers . Wallet ( process . env . PRIVATE_KEY ,  provider );   const  agents  =  new  NexisAgents ( AGENTS_ADDRESS ,  signer );   // 3. Register agent   const  tx  =  await  agents . register ( agentId ,  metadataURI ,  serviceURI );   const  receipt  =  await  tx . wait ();   console . log ( `Agent  ${ agentId }  registered successfully!` );   console . log ( `Transaction hash:  ${ receipt . transactionHash } ` );   return  {     agentId ,     metadataURI ,     serviceURI ,     owner:  signer . address ,     transactionHash:  receipt . transactionHash   }; } // Example usage await  registerAgent (   12345 n ,   {     name:  "Stable Diffusion Agent" ,     description:  "High-quality image generation service" ,     capabilities:  [ "text-to-image" ,  "image-to-image" ,  "inpainting" ],     models:  [ "stable-diffusion-v2.1" ,  "stable-diffusion-xl" ]   },   "https://api.myagent.com/inference" ); 
The metadata URI should point to a JSON structure on IPFS: 
{   "version" :  "1.0" ,   "name" :  "Stable Diffusion Agent" ,   "description" :  "High-quality image generation service powered by Stable Diffusion models" ,   "owner" : {     "name" :  "Acme AI Services" ,     "website" :  "https://acme-ai.com" ,     "contact" :  "support@acme-ai.com"   },   "capabilities" : [     "text-to-image" ,     "image-to-image" ,     "inpainting" ,     "style-transfer"   ],   "models" : [     {       "name" :  "stable-diffusion-v2.1" ,       "version" :  "2.1" ,       "type" :  "text-to-image" ,       "description" :  "Latest Stable Diffusion model" ,       "checksum" :  "sha256:abc123..."     },     {       "name" :  "stable-diffusion-xl" ,       "version" :  "1.0" ,       "type" :  "text-to-image" ,       "description" :  "High resolution image generation" ,       "checksum" :  "sha256:def456..."     }   ],   "pricing" : {     "currency" :  "NEXIS" ,     "per_inference" :  "0.01" ,     "bulk_discount" : {       "100+" :  "0.008" ,       "1000+" :  "0.005"     }   },   "sla" : {     "uptime" :  "99.9%" ,     "response_time_ms" :  5000 ,     "support" :  "24/7"   },   "technical" : {     "api_version" :  "v1" ,     "rate_limit" :  "100/minute" ,     "max_concurrent" :  10 ,     "supported_formats" : [ "png" ,  "jpg" ,  "webp" ]   } } async  function  updateMetadata ( agentId :  bigint ,  newMetadata :  any ) {   const  metadataJSON  =  JSON . stringify ( newMetadata );   const  metadataURI  =  await  uploadToIPFS ( metadataJSON );   const  tx  =  await  agents . updateMetadata ( agentId ,  metadataURI );   await  tx . wait ();   console . log ( `Metadata updated for agent  ${ agentId } ` ); } async  function  updateServiceURI ( agentId :  bigint ,  newServiceURI :  string ) {   const  tx  =  await  agents . updateServiceURI ( agentId ,  newServiceURI );   await  tx . wait ();   console . log ( `Service URI updated for agent  ${ agentId } ` ); } 
Staking System Multi-Asset Staking Agents can stake both ETH and ERC20 tokens to provide economic security: 
Stake ETH
Stake ERC20 Tokens
Python - Stake ETH
Python - Stake ERC20
async  function  stakeETH ( agentId :  bigint ,  amount :  string ) {   const  amountWei  =  ethers . utils . parseEther ( amount );   const  tx  =  await  agents . stakeETH ( agentId , {     value:  amountWei   });   const  receipt  =  await  tx . wait ();   console . log ( `Staked  ${ amount }  ETH for agent  ${ agentId } ` );   // Get updated stake balance   const  stakeBalance  =  await  agents . stakedBalance ( agentId ,  ethers . constants . AddressZero );   console . log ( `Total ETH stake:  ${ ethers . utils . formatEther ( stakeBalance ) }  ETH` );   return  receipt ; } // Example: Stake 1 ETH await  stakeETH ( 12345 n ,  "1.0" ); 
Stake Balances Query different stake states: 
async  function  getStakeInfo ( agentId :  bigint ,  asset :  string ) {   // Get detailed stake view   const  stakeView  =  await  agents . stakeBalances ( agentId ,  asset );   console . log ( `Agent  ${ agentId }  stake for  ${ asset } :` );   console . log ( `  Total:  ${ ethers . utils . formatEther ( stakeView . total ) } ` );   console . log ( `  Locked:  ${ ethers . utils . formatEther ( stakeView . locked ) } ` );   console . log ( `  Available:  ${ ethers . utils . formatEther ( stakeView . available ) } ` );   return  stakeView ; } // Get ETH stake info const  ETH_ADDRESS  =  ethers . constants . AddressZero ; await  getStakeInfo ( 12345 n ,  ETH_ADDRESS ); 
Withdrawal Process The withdrawal process includes an unbonding period for security: 
Request Withdrawal
Claim Withdrawals
Cancel Withdrawal
Python - Request Withdrawal
async  function  requestWithdrawal (   agentId :  bigint ,   asset :  string ,   amount :  string ) {   const  amountWei  =  ethers . utils . parseEther ( amount );   const  tx  =  await  agents . requestWithdrawal ( agentId ,  asset ,  amountWei );   const  receipt  =  await  tx . wait ();   // Extract release time from event   const  event  =  receipt . events ?. find ( e  =>  e . event  ===  "UnbondingInitiated" );   const  releaseTime  =  event ?. args ?. releaseTime ;   console . log ( `Withdrawal requested for  ${ amount } ` );   console . log ( `Release time:  ${ new  Date ( releaseTime  *  1000 ). toISOString () } ` );   return  {  releaseTime ,  transactionHash:  receipt . transactionHash  }; } // Example await  requestWithdrawal ( 12345 n ,  ETH_ADDRESS ,  "0.5" ); 
Viewing Pending Withdrawals async  function  viewPendingWithdrawals ( agentId :  bigint ,  asset :  string ) {   const  count  =  await  agents . pendingWithdrawalCount ( agentId ,  asset );   console . log ( `Pending withdrawals:  ${ count } ` );   for  ( let  i  =  0 ;  i  <  count . toNumber ();  i ++ ) {     const  withdrawal  =  await  agents . pendingWithdrawalAt ( agentId ,  asset ,  i );     const  releaseDate  =  new  Date ( withdrawal . releaseTime  *  1000 );     const  isReady  =  Date . now ()  >=  releaseDate . getTime ();     console . log ( ` \n Withdrawal  ${ i } :` );     console . log ( `  Amount:  ${ ethers . utils . formatEther ( withdrawal . amount ) } ` );     console . log ( `  Release:  ${ releaseDate . toISOString () } ` );     console . log ( `  Status:  ${ isReady  ?  "Ready"  :  "Locked" } ` );   } } Locked Stake Stake can be locked by the Tasks contract during task execution: 
Query Locked Stake
Lock/Unlock (Task Module Only)
async  function  getLockedStake ( agentId :  bigint ,  asset :  string ) {   const  locked  =  await  agents . lockedBalance ( agentId ,  asset );   console . log ( `Locked stake:  ${ ethers . utils . formatEther ( locked ) } ` );   return  locked ; } 
Delegation System The delegation system enables permission-based access control: 
Permission Types bytes32  public  constant  PERMISSION_METADATA  =  keccak256 ( "PERMISSION_METADATA" ); bytes32  public  constant  PERMISSION_INFERENCE  =  keccak256 ( "PERMISSION_INFERENCE" ); bytes32  public  constant  PERMISSION_WITHDRAW  =  keccak256 ( "PERMISSION_WITHDRAW" ); TypeScript Constants
Python Constants
export  const  PERMISSIONS  =  {   METADATA:  ethers . utils . id ( "PERMISSION_METADATA" ),   INFERENCE:  ethers . utils . id ( "PERMISSION_INFERENCE" ),   WITHDRAW:  ethers . utils . id ( "PERMISSION_WITHDRAW" ) }  as  const ; 
Permission Descriptions Permission Description Functions Enabled PERMISSION_METADATAUpdate agent metadata and service URI updateMetadata(), updateServiceURI()PERMISSION_INFERENCERecord inference commitments recordInference()PERMISSION_WITHDRAWManage stake withdrawals requestWithdrawal(), claimWithdrawals(), cancelWithdrawal()
Setting Delegates async  function  setDelegate (   agentId :  bigint ,   delegateAddress :  string ,   permission :  string ,   enabled :  boolean ) {   const  tx  =  await  agents . setDelegate (     agentId ,     delegateAddress ,     permission ,     enabled   );   await  tx . wait ();   console . log ( `Delegate  ${ delegateAddress }  ${ enabled  ?  "granted"  :  "revoked" }  ${ permission } ` ); } // Grant inference permission to operator await  setDelegate (   12345 n ,   "0xOperatorAddress..." ,   PERMISSIONS . INFERENCE ,   true ); // Grant metadata permission to developer await  setDelegate (   12345 n ,   "0xDeveloperAddress..." ,   PERMISSIONS . METADATA ,   true ); // Revoke withdrawal permission await  setDelegate (   12345 n ,   "0xOldOperatorAddress..." ,   PERMISSIONS . WITHDRAW ,   false ); 
Checking Permissions async  function  checkPermission (   agentId :  bigint ,   operatorAddress :  string ,   permission :  string ) :  Promise < boolean > {   const  hasPermission  =  await  agents . hasDelegatedPermission (     agentId ,     operatorAddress ,     permission   );   console . log ( ` ${ operatorAddress }  has  ${ permission } :  ${ hasPermission } ` );   return  hasPermission ; } // Check if operator can record inference const  canRecordInference  =  await  checkPermission (   12345 n ,   "0xOperatorAddress..." ,   PERMISSIONS . INFERENCE ); Reputation System Multi-Dimensional Reputation Nexis tracks agent reputation across four dimensions: 
export  const  REPUTATION_DIMENSIONS  =  {   RELIABILITY:  ethers . utils . id ( "reliability" ),   ACCURACY:  ethers . utils . id ( "accuracy" ),   PERFORMANCE:  ethers . utils . id ( "performance" ),   TRUSTWORTHINESS:  ethers . utils . id ( "trustworthiness" ) }  as  const ; Dimension Meanings 
Reliability Consistency in completing tasks and meeting deadlines. Tracks uptime, completion rate, and deadline adherence. 
Accuracy Quality and correctness of inference outputs. Based on verification success rate and user feedback. 
Performance Speed and efficiency of execution. Measures response time, throughput, and resource efficiency. 
Trustworthiness Overall behavior and community standing. Considers slashing history, disputes, and peer reviews. 
Querying Reputation async  function  getReputationScores ( agentId :  bigint ) {   const  reliability  =  await  agents . getReputation (     agentId ,     REPUTATION_DIMENSIONS . RELIABILITY   );   const  accuracy  =  await  agents . getReputation (     agentId ,     REPUTATION_DIMENSIONS . ACCURACY   );   const  performance  =  await  agents . getReputation (     agentId ,     REPUTATION_DIMENSIONS . PERFORMANCE   );   const  trustworthiness  =  await  agents . getReputation (     agentId ,     REPUTATION_DIMENSIONS . TRUSTWORTHINESS   );   console . log ( ` \n Reputation scores for agent  ${ agentId } :` );   console . log ( `  Reliability:  ${ reliability } ` );   console . log ( `  Accuracy:  ${ accuracy } ` );   console . log ( `  Performance:  ${ performance } ` );   console . log ( `  Trustworthiness:  ${ trustworthiness } ` );   // Get weighted aggregate   const  aggregated  =  await  agents . aggregatedReputation ( agentId );   console . log ( `  Aggregated:  ${ aggregated } ` );   return  {     reliability ,     accuracy ,     performance ,     trustworthiness ,     aggregated   }; } await  getReputationScores ( 12345 n ); 
Reputation Updates Reputation is updated automatically during verification: 
// In attestInference(), verifiers provide reputation deltas const  deltas :  ReputationDelta []  =  [   {     dimension:  REPUTATION_DIMENSIONS . ACCURACY ,     delta:  10 ,   // Positive for successful verification     reason:  "Successful inference verification"   },   {     dimension:  REPUTATION_DIMENSIONS . RELIABILITY ,     delta:  5 ,     reason:  "Timely submission"   } ]; await  agents . connect ( verifier ). attestInference (   inferenceId ,   true ,   attestationURI ,   deltas ); Reputation Weights Administrators can adjust the weight of each dimension: 
// Query current weights async  function  getReputationWeights () {   const  dimensions  =  await  agents . reputationDimensions ();   for  ( const  dim  of  dimensions ) {     const  weight  =  await  agents . reputationWeights ( dim );     console . log ( ` ${ dim } :  ${ weight }  basis points` );   } } // Admin: Update weights (requires DEFAULT_ADMIN_ROLE) async  function  updateWeight ( dimension :  string ,  weightBps :  number ) {   const  tx  =  await  agents . updateReputationWeight ( dimension ,  weightBps );   await  tx . wait ();   console . log ( `Updated weight for  ${ dimension }  to  ${ weightBps }  bps` ); } // Example: Increase accuracy weight to 40% await  updateWeight ( REPUTATION_DIMENSIONS . ACCURACY ,  4000 ); Recording Inference Agents record inference commitments with cryptographic proofs: 
async  function  performAndRecordInference (   agentId :  bigint ,   input :  any ,   taskId :  bigint  =  0 n ) {   // 1. Execute inference (your AI model)   const  output  =  await  runModel ( input );   // 2. Compute hashes   const  inputHash  =  computeInputHash ( input );   const  outputHash  =  computeOutputHash ( output );   const  modelHash  =  computeModelHash ({     name:  "stable-diffusion" ,     version:  "v2.1"   });   // 3. Prepare proof artifact   const  proofArtifact  =  {     input ,     output ,     model:  {       name:  "stable-diffusion" ,       version:  "v2.1"     },     metadata:  {       timestamp:  Date . now (),       executionTime:  1234     }   };   // 4. Upload to IPFS   const  proofURI  =  await  uploadToIPFS ( proofArtifact );   // 5. Record on-chain   const  tx  =  await  agents . recordInference (     agentId ,     inputHash ,     outputHash ,     modelHash ,     taskId ,     proofURI   );   const  receipt  =  await  tx . wait ();   const  event  =  receipt . events ?. find ( e  =>  e . event  ===  "InferenceRecorded" );   const  inferenceId  =  event ?. args ?. inferenceId ;   console . log ( `Inference recorded:  ${ inferenceId } ` );   return  {  inferenceId ,  output  }; } 
Discovery & Querying List All Agents async  function  listAgents ( offset :  number  =  0 ,  limit :  number  =  10 ) {   const  agents  =  await  agentsContract . listAgents ( offset ,  limit );   console . log ( ` \n Agents ( ${ offset }  to  ${ offset  +  agents . length } ):` );   for  ( const  agent  of  agents ) {     console . log ( ` \n Agent  ${ agent . agentId } :` );     console . log ( `  Owner:  ${ agent . owner } ` );     console . log ( `  Metadata:  ${ agent . metadata } ` );     console . log ( `  Service URI:  ${ agent . serviceURI } ` );     console . log ( `  Total Stake:  ${ ethers . utils . formatEther ( agent . totalStake ) } ` );     console . log ( `  Locked Stake:  ${ ethers . utils . formatEther ( agent . lockedStake ) } ` );     console . log ( `  Reputation:  ${ agent . weightedReputation } ` );   }   return  agents ; } Aggregated Statistics async  function  getAggregatedStats () {   const  stats  =  await  agentsContract . aggregatedStats ();   console . log ( ` \n Aggregated Statistics:` );   console . log ( `  Total Agents:  ${ stats . totalAgents } ` );   console . log ( `  Tracked Assets:` );   for  ( let  i  =  0 ;  i  <  stats . assets . length ;  i ++ ) {     const  asset  =  stats . assets [ i ];     const  total  =  stats . totalStakedPerAsset [ i ];     const  assetName  =  asset  ===  ethers . constants . AddressZero  ?  "ETH"  :  asset ;     console . log ( `     ${ assetName } :  ${ ethers . utils . formatEther ( total ) } ` );   }   return  stats ; } Best Practices Minimum Stake Requirements Set minimum stake requirements proportional to the value of tasks your agent will execute. 
// Example: Require 1 ETH minimum stake const  MIN_STAKE  =  ethers . utils . parseEther ( "1.0" ); async  function  ensureMinimumStake ( agentId :  bigint ) {   const  currentStake  =  await  agents . stakedBalance ( agentId ,  ETH_ADDRESS );   if  ( currentStake . lt ( MIN_STAKE )) {     const  needed  =  MIN_STAKE . sub ( currentStake );     await  agents . stakeETH ( agentId , {  value:  needed  });     console . log ( `Added  ${ ethers . utils . formatEther ( needed ) }  ETH stake` );   } } Delegation Security Only delegate permissions to trusted addresses. Use separate addresses for different roles. 
Recommended Setup :
Owner Address : Cold wallet, rarely usedMetadata Address : For updating service informationInference Address : Hot wallet for recording inferencesWithdrawal Address : Multi-sig for financial operations 
Monitoring Reputation // Set up reputation monitoring async  function  monitorReputation ( agentId :  bigint ,  threshold :  number  =  - 50 ) {   const  aggregated  =  await  agents . aggregatedReputation ( agentId );   if  ( aggregated  <  threshold ) {     console . warn ( `⚠️ Low reputation:  ${ aggregated } . Investigate issues!` );     // Send alert, pause operations, etc.   } } Proof Artifact Best Practices 
Include Sufficient Detail : Store all necessary information for verificationUse Compression : Reduce IPFS storage costs with gzipPin Critical Data : Ensure proofs remain accessibleInclude Timestamps : Track inference timingVersion Metadata : Include schema version for compatibility 
Next Steps