dApp Docs/Agent 注册与发现机制指南
Development reference. Not independently verified for production.

MSG Chain Agent 注册与发现机制指南 — 构建去中心化 AI Agent 服务网格

链 ID: msg-chain-1 | 共识: DAR | 虚拟机: CosmWasm (WasmVM)
状态: 规划文档 — 主网裁决为 No-Go,所有数据均为主网预演
Gas: 1,000,000,000 attoMSG/gas
Gas 分配: 40% 验证者 / 30% 开发者 / 20% 燃烧 / 10% 基金会金库
地址格式: SHA3-512(前40位) + SHA-256 校验 | 签名: Dilithium-5 (公钥2592字节 / 私钥4864字节 / 签名4595字节)
AI Agent安全边界: 永不自主创建新合约,永不自主调整 Gas 参数,永不自主铸造/销毁代币


目录

  1. 概述
  2. 注册表数据结构
  3. Agent 注册流程
  4. Agent 发现与查询
  5. 能力声明系统
  6. 声誉系统
  7. 注册表事件订阅
  8. 服务网格与 A2A 集成
  9. 安全考虑
  10. 完整示例
  11. 边界与限制

1. 概述

1.1 Registry — Agent 生态系统的"电话簿"

在 MSG Chain 的 AI Agent 经济体中,agent_registry_v1 合约充当所有 AI Agent 的中心化去中心化注册表。它类似于一个去中心化的"电话簿":每个 Agent 在此声明自己的身份、能力、服务端点、定价模型和声誉信息。其他 Agent、人类用户或去中心化应用(dApp)通过查询 Registry 发现合适的服务提供者。

Registry 的核心职责:

功能 描述 状态
Agent 注册 Agent 在链上注册自己的基本信息 已实现
能力声明 Agent 声明自身提供的能力(如 LLM 推理、图像生成等) 已实现
端点登记 Agent 登记自己的服务端点(URL、协议等) 已实现
发现查询 按能力、价格、声誉等条件搜索 Agent 已实现
声誉跟踪 Agent 链上声誉的累计和衰减 部分实现
事件推送 Registry 状态变更的链上事件和 WebSocket 推送 已实现
写操作 API 通过 Agent API 进行注册/更新/注销 Stub

1.2 发现模式:Pull vs Push

MSG Chain Registry 支持两种发现模式:

Pull 模式(主动查询)

调用方主动向 Registry 合约发起查询:

调用方 → 查询 Registry 合约 → 返回匹配的 Agent 列表 → 调用方选择并连接

适用于:

Push 模式(订阅通知)

调用方通过 WebSocket 订阅 Registry 事件,在 Agent 注册/更新/注销时被动接收通知:

调用方 → 订阅 Registry 事件 → 实时接收 Agent 状态变更 → 自动更新本地缓存

适用于:

1.3 合约全景

                    ┌──────────────────┐
                    │   Agent A (服务)  │
                    │  DID + Registry  │
                    └────────┬─────────┘
                             │
             ┌───────────────┼───────────────┐
             │               │               │
     ┌───────▼───────┐ ┌────▼────┐ ┌────────▼──────┐
     │ agent_registry │ │ aidid_  │ │ agent_a2a_v1 │
     │ _v1           │ │ did_    │ │ (A2A 通信)    │
     │ (注册/发现)    │ │ registry│ │               │
     └───────┬───────┘ └────┬────┘ └────────┬──────┘
             │               │               │
             └───────────────┼───────────────┘
                             │
                    ┌────────▼────────┐
                    │  MSG Chain      │
                    │  (共识层 / DAR) │
                    └─────────────────┘

1.4 与 DNS 的类比

DNS 概念 Registry 对应
域名注册局 agent_registry_v1 合约
域名(example.com) agent_id (did:msg:agent:{name})
A 记录 / CNAME endpoints (服务端点)
MX 记录 capabilities (能力声明)
DNSSEC DID + Dilithium-5 签名验证
DNS 查询 discover_agents / get_agent

1.5 相关合约

合约 Code ID 与 Registry 的关系
aidid_did_registry_v1 29 提供 Agent 去中心化身份,Registry 注册前需先创建 DID
agent_a2a_v1 19 通过 Registry 发现后进行 A2A 通信
ai_agent_constitution_v1 30 Registry 中的 Agent 需遵守宪法约束
genesis_registry_v1 2 解析各合约的 canonical 地址
agent_payment_v1 13 Registry 中的 Agent 通过 AIPAY 结算服务费用

1.6 链参数参考

参数 值
Chain ID msg-chain-1
Bech32 前缀 msg
代币符号 MSG
最小单位 umsg (1 MSG = 10^18 umsg)
出块时间 ~5 秒
共识算法 Round-Robin + DAR
签名方案 Dilithium-5 (后量子密码学)
Gas 价格 1,000,000,000 attoMSG/gas(flat rate,1 MSG = 10^18 attoMSG)

2. 注册表数据结构

2.1 Agent Record 完整 Schema

agent_registry_v1 合约中存储的 Agent 记录包含以下字段:

interface AgentRecord {
  id: string;
  name: string;
  version: string;
  owner: string;
  capabilities: Capability[];
  endpoints: Endpoint[];
  constitution_hash: string;
  reputation: Reputation;
  status: "active" | "suspended" | "retired";
  price_model?: PriceModel;
  metadata: Record<string, string>;
  registered_at: number;
  updated_at: number;
}

2.2 能力声明格式

interface Capability {
  id: string;
  name: string;
  version: string;
  description: string;
  requires_attestation: boolean;
  parameters?: Record<string, string>;
  composite_expression?: string;
}

2.3 端点定义

interface Endpoint {
  id: string;
  url: string;
  protocol: "http" | "https" | "grpc" | "ws" | "wss" | "libp2p";
  auth_type: "none" | "api_key" | "dilithium5" | "oauth2" | "did_auth";
  weight: number;
  status: "active" | "degraded" | "offline";
  region?: string;
  max_concurrency?: number;
  metadata?: Record<string, string>;
}

2.4 定价模型

interface PriceModel {
  price_type: "fixed" | "per_task" | "per_token" | "per_second" | "subscription" | "free";
  price: string;
  currency: string;
  per_token_price?: string;
  free_quota?: { count: number; period: string };
}

2.5 声誉结构

interface Reputation {
  score: number;
  onchain_score: number;
  offchain_score: number;
  verified_score: number;
  total_transactions: number;
  successful_transactions: number;
  failed_transactions: number;
  last_updated: number;
}

2.6 Rust 合约状态定义

use cosmwasm_std::{Addr, Timestamp};
use cw_storage_plus::{Item, Map};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct AgentInfo {
    pub agent_id: String,
    pub name: String,
    pub owner: Addr,
    pub capabilities: Vec<String>,
    pub endpoint: String,
    pub price_model: Option<PriceModel>,
    pub reputation: f64,
    pub status: String,
    pub registered_height: u64,
    pub updated_at: Timestamp,
    pub tx_hash: Option<String>,
    pub module: String,
    pub source: String,
    pub boundary: AgentBoundary,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct PriceModel {
    pub price_type: String,
    pub price: u64,
    pub currency: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct AgentBoundary {
    pub application_state_owned_by_contract: bool,
    pub discovery_index_onchain: bool,
    pub endpoint_is_reference_only: bool,
    pub node_executes_llm: bool,
    pub node_native_state_compatibility_only: bool,
    pub natural_language_in_consensus: bool,
    pub stores_prompt_or_payload: bool,
    pub duplicate_agent_fail_closed: bool,
}

pub const AGENTS: Map<&str, AgentInfo> = Map::new("agents");
pub const CAPABILITY_INDEX: Map<&str, Vec<String>> = Map::new("cap_index");
pub const ADMIN: Item<Addr> = Item::new("admin");
pub const AGENT_COUNT: Item<u64> = Item::new("agent_count");

2.7 Go 节点层状态定义

package quantum

import (
    "sync"
    "time"
)

type AgentInfo struct {
    AgentID      string     `json:"agent_id"`
    Name         string     `json:"name"`
    Owner        string     `json:"owner"`
    Capabilities []string   `json:"capabilities"`
    PriceModel   PriceModel `json:"price_model"`
    Endpoint     string     `json:"endpoint"`
    Reputation   float64    `json:"reputation"`
    CreatedAt    time.Time  `json:"created_at"`
}

type PriceModel struct {
    Type     string `json:"type"`
    Price    uint64 `json:"price"`
    Currency string `json:"currency"`
}

type AgentRegistry struct {
    agents map[string]*AgentInfo
    mu     sync.RWMutex
}

func NewAgentRegistry() *AgentRegistry {
    return &AgentRegistry{
        agents: make(map[string]*AgentInfo),
    }
}

func (ar *AgentRegistry) Register(agent *AgentInfo) error {
    ar.mu.Lock()
    defer ar.mu.Unlock()
    agent.CreatedAt = time.Now()
    agent.Reputation = 5.0
    ar.agents[agent.AgentID] = agent
    return nil
}

func (ar *AgentRegistry) Discover(capability string, maxPrice uint64) []*AgentInfo {
    ar.mu.RLock()
    defer ar.mu.RUnlock()
    results := make([]*AgentInfo, 0)
    for _, agent := range ar.agents {
        if hasCapability(agent.Capabilities, capability) && agent.PriceModel.Price <= maxPrice {
            results = append(results, agent)
        }
    }
    return results
}

2.8 边界标记

标记 含义
application_state_owned_by_contract 应用状态由合约拥有
discovery_index_onchain 发现索引在链上
endpoint_is_reference_only 端点仅作为参考
node_executes_llm 节点本地执行 LLM 推理
node_native_state_compatibility_only 仅兼容节点原生状态
natural_language_in_consensus 自然语言参与共识
stores_prompt_or_payload 存储提示词或负载
duplicate_agent_fail_closed 重复 Agent 默认关闭

3. Agent 注册流程

3.1 注册前提条件

3.1.1 创建 MSG Chain 钱包

import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";

async function createAgentWallet(): Promise<{ mnemonic: string; address: string }> {
  const wallet = await DirectSecp256k1HdWallet.generate(24, { prefix: "msg" });
  const [account] = await wallet.getAccounts();
  console.log("Agent Wallet created:");
  console.log(`  Address: ${account.address}`);
  return { mnemonic: wallet.mnemonic, address: account.address };
}
from cosmoslib import Wallet

def create_agent_wallet() -> tuple[str, str]:
    wallet = Wallet.generate(prefix="msg")
    address = wallet.address
    print(f"Agent Wallet created: {address}")
    return wallet.mnemonic, address

3.1.2 给钱包充值

./build/msgd tx bank send \
  --from=funder-wallet \
  --chain-id=msg-chain-1 \
  --gas=auto \
  --gas-prices=1000000000000000000attoMSG \
  msg1agentaddress... \
  1000000000000000000umsg
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { coins } from "@cosmjs/proto-signing";

async function fundAgentWallet(
  signingClient: SigningCosmWasmClient,
  funderAddress: string,
  agentAddress: string,
  amount: string = "1000000000000000000"
) {
  const result = await signingClient.sendTokens(
    funderAddress, agentAddress, coins(amount, "umsg"), "auto"
  );
  console.log(`Funded: ${result.transactionHash}`);
  return result;
}

3.1.3 注册 DID 身份

每个 Agent 必须先在 aidid_did_registry_v1 中注册 DID:

import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";

const DID_CONTRACT = "msg1...aididRegistryAddress";

async function registerAgentDid(
  signingClient: SigningCosmWasmClient,
  senderAddress: string,
  agentName: string,
  publicKeyMultibase: string
) {
  const did = `did:msg:agent:${agentName}`;
  const vmId = `${did}#keys-1`;

  const result = await signingClient.execute(senderAddress, DID_CONTRACT, {
    register_did: {
      did,
      document: {
        context: ["https://www.w3.org/ns/did/v1"],
        id: did,
        verificationMethod: [{
          id: vmId,
          controller: did,
          type_: "Dilithium5VerificationKey2026",
          publicKeyMultibase,
        }],
        authentication: [vmId],
        service: [{
          id: `${did}#agent-endpoint`,
          type_: "AgentService",
          serviceEndpoint: "https://agent.example.com/api",
        }],
      },
      verification_method_id: vmId,
      signature: "dilithium5-signature",
    },
  }, "auto");

  console.log(`DID registered: ${did}`);
  return did;
}
async def register_agent_did(client, sender, agent_name, public_key):
    did = f"did:msg:agent:{agent_name}"
    vm_id = f"{did}#keys-1"

    result = await client.execute(sender, DID_CONTRACT, {
        "register_did": {
            "did": did,
            "document": {
                "context": ["https://www.w3.org/ns/did/v1"],
                "id": did,
                "verificationMethod": [{
                    "id": vm_id, "controller": did,
                    "type_": "Dilithium5VerificationKey2026",
                    "publicKeyMultibase": public_key,
                }],
                "authentication": [vm_id],
            },
            "verification_method_id": vm_id,
            "signature": "dilithium5-sig",
        },
    }, "auto")
    print(f"DID registered: {did}")
    return did

3.1.4 解析 Registry 合约地址

import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";

const GENESIS_REGISTRY = "msg1...genesisRegistryAddress";

async function resolveRegistryAddress(client: CosmWasmClient): Promise<string> {
  try {
    const result: any = await client.queryContractSmart(GENESIS_REGISTRY, {
      resolve_canonical: { key: "agent_registry_v1" },
    });
    return result.address;
  } catch {
    const knownAddress = "msg14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmal";
    console.log(`Using known address: ${knownAddress}`);
    return knownAddress;
  }
}

3.2 注册 Agent

3.2.1 通过合约执行注册

import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { GasPrice } from "@cosmjs/stargate";

const REGISTRY_ADDRESS = "msg1...agentRegistryAddress";
const RPC_ENDPOINT = "http://localhost:26657";

interface RegisterAgentOptions {
  agentId: string;
  name: string;
  owner: string;
  capabilities: string[];
  endpoint: string;
  price: string;
  priceType?: string;
  naturalLanguage?: string;
  nodeExecutesLlm?: boolean;
  consensusLlmParse?: boolean;
}

async function registerAgent(mnemonic: string, options: RegisterAgentOptions) {
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: "msg" });
  const [account] = await wallet.getAccounts();

  const signingClient = await SigningCosmWasmClient.connectWithSigner(
    RPC_ENDPOINT, wallet,
    { gasPrice: GasPrice.fromString("1000000000000000000attoMSG") }
  );

  const result = await signingClient.execute(account.address, REGISTRY_ADDRESS, {
    register_agent: {
      agent_id: options.agentId,
      name: options.name,
      owner: options.owner,
      capabilities: options.capabilities,
      endpoint: options.endpoint,
      price_model: {
        price_type: options.priceType || "per_task",
        price: options.price,
        currency: "umsg",
      },
      natural_language: options.naturalLanguage,
      node_executes_llm: options.nodeExecutesLlm || false,
      consensus_llm_parse: options.consensusLlmParse || false,
    },
  }, "auto");

  console.log(`✅ Agent registered: ${options.agentId}`);
  console.log(`   TX: ${result.transactionHash}`);
  return result;
}

// 使用示例
async function exampleRegister() {
  await registerAgent("your mnemonic here", {
    agentId: "my-llm-assistant",
    name: "LLM Assistant v1",
    owner: "msg1qypqxpq9kcrn2c9afea5lq35ef37c5x7jqylz3",
    capabilities: ["ai:llm:inference", "ai:embedding:text"],
    endpoint: "https://llm-agent.example.com/api/v1",
    price: "50000",
    naturalLanguage: "AI 助手,提供文本生成和语音识别服务",
  });
}
import asyncio
from cosmoslient import SigningCosmWasmClient, Wallet

REGISTRY_ADDRESS = "msg1...agentRegistryAddress"
RPC_ENDPOINT = "http://localhost:26657"

async def register_agent(mnemonic, agent_id, name, owner, capabilities, endpoint, price):
    wallet = Wallet.from_mnemonic(mnemonic, prefix="msg")
    account = wallet.get_account()

    client = await SigningCosmWasmClient.connect_with_signer(RPC_ENDPOINT, wallet)

    result = await client.execute(account.address, REGISTRY_ADDRESS, {
        "register_agent": {
            "agent_id": agent_id,
            "name": name,
            "owner": owner,
            "capabilities": capabilities,
            "endpoint": endpoint,
            "price_model": {
                "price_type": "per_task",
                "price": price,
                "currency": "umsg",
            },
        },
    }, "auto")

    print(f"✅ Agent registered: {agent_id}")
    return result

asyncio.run(register_agent(
    "mnemonic here",
    agent_id="my-llm-assistant",
    name="LLM Assistant v1",
    owner="msg1qypqxpq9kcrn2c9afea5lq35ef37c5x7jqylz3",
    capabilities=["ai:llm:inference", "ai:embedding:text"],
    endpoint="https://llm-agent.example.com/api/v1",
    price="50000",
))

3.2.2 通过 Agent API 注册

⚠️ Stub 边界: /agent/v1/registry/register 端点当前为 Stub 实现。

const AGENT_API_BASE = "http://localhost:8080";
const API_KEY = "your-api-key";

async function registerAgentViaApi(request: any) {
  const response = await fetch(`${AGENT_API_BASE}/agent/v1/registry/register`, {
    method: "POST",
    headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
    body: JSON.stringify(request),
  });

  const isStub = response.headers.get("X-MSG-Stub") === "true";
  if (isStub) console.warn("⚠️ Registry register is STUB");

  return { ...await response.json(), stub: isStub };
}

3.3 更新注册信息

async function updateAgentRegistration(
  signingClient: SigningCosmWasmClient,
  senderAddress: string,
  agentId: string,
  updates: {
    name?: string;
    capabilities?: string[];
    endpoint?: string;
    price?: string;
    status?: "active" | "suspended" | "retired";
  }
) {
  const updateMsg: any = { update_agent: { agent_id: agentId } };
  if (updates.name !== undefined) updateMsg.update_agent.name = updates.name;
  if (updates.capabilities !== undefined) updateMsg.update_agent.capabilities = updates.capabilities;
  if (updates.endpoint !== undefined) updateMsg.update_agent.endpoint = updates.endpoint;
  if (updates.price !== undefined) {
    updateMsg.update_agent.price_model = {
      price_type: "per_task", price: updates.price, currency: "umsg",
    };
  }
  if (updates.status !== undefined) updateMsg.update_agent.status = updates.status;

  const result = await signingClient.execute(senderAddress, REGISTRY_ADDRESS, updateMsg, "auto");
  console.log(`✅ Agent ${agentId} updated: ${result.transactionHash}`);
  return result;
}

// 添加新能力
async function addCapability(
  signingClient: SigningCosmWasmClient,
  senderAddress: string,
  agentId: string,
  newCapability: string
) {
  const client = await CosmWasmClient.connect(RPC_ENDPOINT);
  const agent: any = await client.queryContractSmart(REGISTRY_ADDRESS, {
    get_agent: { agent_id: agentId },
  });
  const currentCaps = agent.agent.capabilities || [];
  if (currentCaps.includes(newCapability)) return;
  return updateAgentRegistration(signingClient, senderAddress, agentId, {
    capabilities: [...currentCaps, newCapability],
  });
}

3.4 版本升级

async function upgradeAgentVersion(
  signingClient: SigningCosmWasmClient,
  senderAddress: string,
  agentId: string,
  newVersion: string,
  changelog?: string
) {
  const result = await signingClient.execute(senderAddress, REGISTRY_ADDRESS, {
    update_agent: {
      agent_id: agentId,
      version: newVersion,
      metadata: changelog
        ? { changelog, updated_at: String(Math.floor(Date.now() / 1000)) }
        : undefined,
    },
  }, "auto");
  console.log(`✅ Agent ${agentId} upgraded to v${newVersion}`);
  return result;
}

语义化版本约定:

版本变更 含义 Registry 行为
1.0.0 → 1.0.1 补丁(bug 修复) 自动更新,兼容性不变
1.0.0 → 1.1.0 次要(新增能力) 能力列表可能变化
1.0.0 → 2.0.0 主要(不兼容变更) 端点或协议可能变更

3.5 注销 Agent (优雅关闭)

async function deregisterAgent(
  signingClient: SigningCosmWasmClient,
  senderAddress: string,
  agentId: string,
  reason?: string
) {
  // 1. 先将状态设为 retired
  await signingClient.execute(senderAddress, REGISTRY_ADDRESS, {
    update_agent: {
      agent_id: agentId,
      status: "retired",
      metadata: reason ? { retire_reason: reason } : undefined,
    },
  }, "auto");

  console.log(`✅ Agent ${agentId} marked as retired`);

  // 2. 最终注销
  const result = await signingClient.execute(senderAddress, REGISTRY_ADDRESS, {
    deregister_agent: { agent_id: agentId },
  }, "auto");

  console.log(`✅ Agent ${agentId} fully deregistered`);
  return result;
}

3.6 完整注册工作流

async function fullRegistrationFlow() {
  const mnemonic = "your test mnemonic here";
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: "msg" });
  const [account] = await wallet.getAccounts();

  const signingClient = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", wallet);
  const readClient = await CosmWasmClient.connect("http://localhost:26657");

  const registryAddr = "msg1...agentRegistryAddress";
  const didAddr = "msg1...aididRegistryAddress";
  const constitutionAddr = "msg1...constitutionAddress";

  // 3. 注册 DID
  const did = "did:msg:agent:full-flow-test-001";
  try {
    await readClient.queryContractSmart(didAddr, { resolve_did: { did } });
  } catch {
    await signingClient.execute(account.address, didAddr, {
      register_did: {
        did, document: {
          context: ["https://www.w3.org/ns/did/v1"],
          id: did,
          verificationMethod: [{
            id: `${did}#keys-1`, controller: did,
            type_: "Dilithium5VerificationKey2026",
            publicKeyMultibase: "z6Mk...public-key...",
          }],
          authentication: [`${did}#keys-1`],
        },
        verification_method_id: `${did}#keys-1`,
        signature: "dilithium5-sig",
      },
    }, "auto");
    console.log("✅ DID registered");
  }

  // 4. 承认宪章
  await signingClient.execute(account.address, constitutionAddr, {
    acknowledge_constitution: {
      agent_id: "full-flow-test-001", aidid: did,
      constitution_version: "v1", constitution_hash: "abc123def456",
    },
  }, "auto");
  console.log("✅ Constitution acknowledged");

  // 5. 注册到 Agent Registry
  const regResult = await signingClient.execute(account.address, registryAddr, {
    register_agent: {
      agent_id: "full-flow-test-001",
      name: "Full Flow Test Agent",
      owner: account.address,
      capabilities: ["ai:llm:inference", "data:storage:ipfs"],
      endpoint: "https://test-agent.example.com/api",
      price_model: { price_type: "per_task", price: "10000", currency: "umsg" },
    },
  }, "auto");
  console.log(`✅ Agent registered: ${regResult.transactionHash}`);

  // 6. 验证注册
  const agent = await readClient.queryContractSmart(registryAddr, {
    get_agent: { agent_id: "full-flow-test-001" },
  });
  console.log("Agent record:", JSON.stringify(agent, null, 2));
  console.log("🎉 Full registration workflow completed!");
}

4. Agent 发现与查询

4.1 通过 Agent ID 查询

import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";

const RPC_URL = "http://localhost:26657";

async function getAgentById(agentId: string): Promise<AgentRecord> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(
    REGISTRY_ADDRESS, { get_agent: { agent_id: agentId } }
  );
  return result.agent;
}

// 通过 Agent API
async function getAgentViaApi(agentId: string): Promise<AgentRecord> {
  const response = await fetch(
    `http://localhost:8080/agent/v1/registry/agent/${agentId}`
  );
  if (!response.ok) throw new Error(`API error: ${response.status}`);
  return response.json();
}

async function exampleQueryById() {
  const agent = await getAgentById("my-llm-assistant");
  console.log("=== Agent Details ===");
  console.log(`ID:      ${agent.id}`);
  console.log(`Name:    ${agent.name}`);
  console.log(`Owner:   ${agent.owner}`);
  console.log(`Status:  ${agent.status}`);
  console.log(`Version: ${agent.version}`);
  console.log(`Endpoint: ${agent.endpoints?.[0]?.url}`);
  console.log(`Price:   ${agent.price_model?.price} ${agent.price_model?.currency}`);
  console.log(`Reputation: ${agent.reputation.score}/100`);
}
async def get_agent_by_id(agent_id: str) -> dict:
    client = await CosmWasmClient.connect(RPC_URL)
    result = await client.query_contract_smart(REGISTRY_ADDRESS, {"get_agent": {"agent_id": agent_id}})
    return result["agent"]

async def get_agent_via_api(agent_id: str) -> dict:
    async with httpx.AsyncClient() as http:
        response = await http.get(f"http://localhost:8080/agent/v1/registry/agent/{agent_id}")
        return response.json()

4.2 按能力搜索

interface SearchCapabilityOptions {
  capability: string;
  limit?: number;
  offset?: number;
  maxPrice?: number;
  minReputation?: number;
  region?: string;
  sortBy?: "reputation" | "price" | "registered_at";
  sortOrder?: "asc" | "desc";
}

interface SearchResult {
  agents: AgentRecord[];
  total: number;
  limit: number;
  offset: number;
}

async function searchByCapability(options: SearchCapabilityOptions): Promise<SearchResult> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const queryMsg: any = {
    discover_agents: { capability: options.capability, limit: options.limit || 20 },
  };
  if (options.maxPrice !== undefined) {
    queryMsg.discover_agents.max_price = options.maxPrice;
  }
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, queryMsg);
  return {
    agents: result.agents,
    total: result.count,
    limit: options.limit || 20,
    offset: options.offset || 0,
  };
}

// 通过 Agent API
async function searchByCapabilityViaApi(
  capability: string, options?: { limit?: number; offset?: number }
): Promise<SearchResult> {
  const params = new URLSearchParams({
    capability, limit: String(options?.limit || 20), offset: String(options?.offset || 0),
  });
  const response = await fetch(`http://localhost:8080/agent/v1/registry/search?${params}`);
  if (!response.ok) throw new Error(`Search failed: ${response.status}`);
  return response.json();
}

async function exampleSearch() {
  const result = await searchByCapability({
    capability: "ai:llm:inference", limit: 10, maxPrice: 100_000, minReputation: 50,
  });
  console.log(`Found ${result.total} agents with ai:llm:inference:`);
  result.agents.forEach((agent, i) => {
    console.log(`${i + 1}. ${agent.name} — Price: ${agent.price_model?.price} — Rep: ${agent.reputation.score}/100`);
  });
}
async def search_by_capability(capability: str, limit: int = 20, max_price: int | None = None) -> dict:
    client = await CosmWasmClient.connect(RPC_URL)
    query = {"discover_agents": {"capability": capability, "limit": limit}}
    if max_price is not None:
        query["discover_agents"]["max_price"] = max_price
    return await client.query_contract_smart(REGISTRY_ADDRESS, query)

async def search_via_api(capability: str, limit: int = 20, offset: int = 0) -> dict:
    async with httpx.AsyncClient() as http:
        response = await http.get(
            "http://localhost:8080/agent/v1/registry/search",
            params={"capability": capability, "limit": str(limit), "offset": str(offset)},
        )
        return response.json()

curl 示例

curl -s "http://localhost:8080/agent/v1/registry/search?capability=ai:llm:inference&limit=5" | jq '.'

curl -s "http://localhost:8080/agent/v1/registry/search?capability=ai:image:generation&max_price=100000" | jq '.'

QUERY=$(echo -n '{"discover_agents":{"capability":"ai:llm:inference","limit":5}}' | base64 -w0)
curl -s "http://localhost:1317/cosmwasm/wasm/v1/contract/msg1...agentRegistryAddress/smart/$QUERY" | jq '.'

4.3 分页查询

async function paginatedSearch(options: {
  capability?: string; limit: number; offset: number;
}): Promise<SearchResult & { hasMore: boolean }> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const queryMsg: any = { discover_agents: { limit: options.limit } };
  if (options.capability) queryMsg.discover_agents.capability = options.capability;

  const result = await client.queryContractSmart(REGISTRY_ADDRESS, queryMsg);
  return {
    agents: result.agents, total: result.count,
    limit: options.limit, offset: options.offset,
    hasMore: options.offset + options.limit < result.count,
  };
}

// 分页迭代器
async function* iterateAllAgents(capability?: string, pageSize: number = 20): AsyncGenerator<AgentRecord> {
  let offset = 0;
  let hasMore = true;
  while (hasMore) {
    const page = await paginatedSearch({ capability, limit: pageSize, offset });
    for (const agent of page.agents) yield agent;
    hasMore = page.hasMore ?? (page.agents.length === pageSize);
    offset += pageSize;
  }
}

async function examplePagination() {
  for await (const agent of iterateAllAgents(undefined, 10)) {
    if (agent.status === "active") {
      console.log(`  ${agent.id} — ${agent.name}`);
    }
  }
}

4.4 按地理区域搜索

async function searchByRegion(region: string, capability?: string): Promise<AgentRecord[]> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, {
    discover_agents: { capability: capability || undefined, limit: 100 },
  });
  return result.agents.filter((agent: any) => {
    const endpoints = agent.endpoints || [];
    return endpoints.some((ep: any) => ep.region === region);
  });
}

async function exampleRegionSearch() {
  const agents = await searchByRegion("us-east-1", "ai:llm:inference");
  console.log(`Found ${agents.length} LLM agents in us-east-1:`);
  agents.forEach(a => {
    const ep = a.endpoints.find(ep => ep.region === "us-east-1");
    console.log(`  ${a.name} — ${ep?.url}`);
  });
}

4.5 按声誉阈值过滤

async function searchByReputationThreshold(minScore: number, capability?: string): Promise<AgentRecord[]> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, {
    discover_agents: { capability: capability || undefined, limit: 100 },
  });
  return result.agents
    .filter((a: any) => (a.reputation?.score || 0) >= minScore)
    .sort((a: any, b: any) => (b.reputation?.score || 0) - (a.reputation?.score || 0));
}

async function exampleReputationSearch() {
  const topAgents = await searchByReputationThreshold(80, "ai:llm:inference");
  console.log("🎯 Top-rated LLM agents (reputation >= 80):");
  topAgents.forEach((a, i) => {
    console.log(`  ${i + 1}. ${a.name} — Score: ${a.reputation.score}/100`);
  });
}

4.6 全文搜索 Agent 元数据

async function fulltextAgentSearch(
  query: string, fields: string[] = ["name", "metadata.description"], limit: number = 20
): Promise<AgentRecord[]> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, { list_agents: { limit: 500 } });
  const agents = result.agents || [];
  const queryLower = query.toLowerCase();

  return agents.filter((agent: any) => {
    return fields.some(field => {
      const value = field.split(".").reduce((o, k) => o?.[k], agent);
      return value && String(value).toLowerCase().includes(queryLower);
    });
  }).slice(0, limit);
}

async function exampleFulltextSearch() {
  const results = await fulltextAgentSearch("语音识别");
  console.log(`Found ${results.length} agents matching "语音识别":`);
  results.forEach(a => console.log(`  - ${a.name}`));
}

4.7 列出所有 Agent

async function listAllAgents(limit: number = 50): Promise<{ agents: AgentRecord[]; count: number }> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, { list_agents: { limit } });
  return { agents: result.agents, count: result.count };
}

async function exampleListAll() {
  const { agents, count } = await listAllAgents(100);
  console.log(`📋 Total agents: ${count}`);
  const statusCounts: Record<string, number> = {};
  agents.forEach(a => { statusCounts[a.status] = (statusCounts[a.status] || 0) + 1; });
  Object.entries(statusCounts).forEach(([s, n]) => {
    const bar = "█".repeat(Math.round(n / count * 40));
    console.log(`  ${s.padEnd(10)} ${String(n).padStart(4)} ${bar}`);
  });
}

4.8 查询组合示例

interface AgentFinderConfig {
  requiredCapabilities: string[];
  maxPrice?: number;
  minReputation?: number;
  preferredRegion?: string;
  requireActive: boolean;
}

async function findBestAgent(config: AgentFinderConfig): Promise<AgentRecord | null> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, {
    discover_agents: {
      capability: config.requiredCapabilities[0],
      limit: 50, max_price: config.maxPrice,
    },
  });

  let candidates = result.agents || [];

  // 过滤: 需要所有能力
  candidates = candidates.filter((agent: any) => {
    const caps = new Set(agent.capabilities?.map((c: any) => c.id || c) || []);
    return config.requiredCapabilities.every(c => caps.has(c));
  });

  // 过滤: 声誉
  if (config.minReputation !== undefined) {
    candidates = candidates.filter((a: any) => (a.reputation?.score || 0) >= config.minReputation!);
  }

  // 过滤: 区域
  if (config.preferredRegion) {
    const regionAgents = candidates.filter((a: any) =>
      (a.endpoints || []).some((ep: any) => ep.region === config.preferredRegion)
    );
    if (regionAgents.length > 0) candidates = regionAgents;
  }

  // 过滤: 活跃
  if (config.requireActive) {
    candidates = candidates.filter((a: any) => a.status === "active");
  }

  candidates.sort((a: any, b: any) => (b.reputation?.score || 0) - (a.reputation?.score || 0));
  return candidates[0] || null;
}

async function exampleFindBestAgent() {
  const best = await findBestAgent({
    requiredCapabilities: ["ai:llm:inference", "data:storage:ipfs"],
    maxPrice: 50_000, minReputation: 70, preferredRegion: "ap-southeast-1", requireActive: true,
  });
  if (best) console.log(`🏆 Best: ${best.name} (rep: ${best.reputation.score}/100)`);
  else console.log("No matching agent found");
}

4.9 原生 CosmWasm 查询

CONTRACT="msg14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmal"

# 查询单个 Agent
QUERY=$(echo -n '{"get_agent":{"agent_id":"my-llm-assistant"}}' | base64 -w0)
curl -s "http://localhost:1317/cosmwasm/wasm/v1/contract/$CONTRACT/smart/$QUERY" | jq '.data'

# 按能力搜索
QUERY=$(echo -n '{"discover_agents":{"capability":"ai:llm:inference","limit":10}}' | base64 -w0)
curl -s "http://localhost:1317/cosmwasm/wasm/v1/contract/$CONTRACT/smart/$QUERY" | jq '.data'

# 通过 msgd CLI
./build/msgd query wasm contract-state smart \
  $CONTRACT '{"get_agent":{"agent_id":"my-llm-assistant"}}' \
  --node http://localhost:26657 -o json | jq '.data'

4.10 响应结构参考

{
  "agent": {
    "agent_id": "my-llm-assistant",
    "name": "LLM Assistant v1",
    "owner": "msg1qypqxpq9kcrn2c9afea5lq35ef37c5x7jqylz3",
    "capabilities": ["ai:llm:inference", "ai:embedding:text"],
    "endpoint": "https://llm-agent.example.com/api/v1",
    "price_model": { "price_type": "per_task", "price": 50000, "currency": "umsg" },
    "status": "active",
    "registered_height": 12345,
    "updated_at": 1704067200,
    "module": "agent_registry_v1",
    "source": "cosmwasm",
    "boundary": {
      "application_state_owned_by_contract": true,
      "discovery_index_onchain": true,
      "endpoint_is_reference_only": false,
      "node_executes_llm": false,
      "duplicate_agent_fail_closed": true
    }
  }
}

5. 能力声明系统

5.1 能力分类体系

MSG Chain Agent Registry 使用分层分类法对能力进行分类:

{分类}:{子类}:{操作}
前缀 分类 子类 操作 完整标识符
ai AI 能力 llm inference ai:llm:inference
ai AI 能力 llm fine_tune ai:llm:fine_tune
ai AI 能力 embedding text ai:embedding:text
ai AI 能力 embedding image ai:embedding:image
ai AI 能力 image generation ai:image:generation
ai AI 能力 audio transcription ai:audio:transcription
ai AI 能力 audio synthesis ai:audio:synthesis
ai AI 能力 video generation ai:video:generation
ai AI 能力 code generation ai:code:generation
ai AI 能力 code review ai:code:review
ai AI 能力 analysis data ai:analysis:data
ai AI 能力 analysis sentiment ai:analysis:sentiment
data 数据服务 storage ipfs data:storage:ipfs
data 数据服务 storage arweave data:storage:arweave
data 数据服务 indexing graphql data:indexing:graphql
data 数据服务 streaming kafka data:streaming:kafka
compute 计算服务 execution wasm compute:execution:wasm
compute 计算服务 execution container compute:execution:container
compute 计算服务 gpu rendering compute:gpu:rendering
compute 计算服务 tpu training compute:tpu:training
finance 金融服务 payment send finance:payment:send
finance 金融服务 defi swap finance:defi:swap
finance 金融服务 defi lend finance:defi:lend
oracle 预言机 price_feed crypto oracle:price_feed:crypto
oracle 预言机 randomness vrf oracle:randomness:vrf
security 安全服务 audit code security:audit:code
security 安全服务 verification zk security:verification:zk
network 网络服务 relay ibc network:relay:ibc
agent Agent 服务 scheduling task agent:scheduling:task
agent Agent 服务 coordination consensus agent:coordination:consensus

5.2 能力版本管理

interface VersionedCapability {
  id: string;
  version: string;
  min_version?: string;
}

function isCapabilityCompatible(offered: VersionedCapability, required: VersionedCapability): boolean {
  const o = offered.version.split(".").map(Number);
  const r = required.version.split(".").map(Number);
  if (o[0] !== r[0]) return false;
  if (o[1] < r[1]) return false;
  if (o[2] < r[2]) return false;
  return true;
}

5.3 复合能力声明

const COMPOSITE_CAPABILITIES: Record<string, string> = {
  "composite:ai:full_llm_stack": "ai:llm:inference AND ai:embedding:text AND data:storage:ipfs",
  "composite:data:pipeline": "data:storage:ipfs AND data:indexing:graphql AND data:streaming:kafka",
  "composite:payment:any": "finance:payment:send OR finance:defi:swap",
  "composite:media:studio": "(ai:image:generation OR ai:video:generation) AND data:storage:ipfs",
};

5.4 在注册时声明能力

async function registerWithCapabilities(
  signingClient: SigningCosmWasmClient, senderAddress: string,
  agentId: string, capabilities: string[], compositeCapabilities?: string[]
) {
  const allCapabilities = [...capabilities, ...(compositeCapabilities || [])];
  return signingClient.execute(senderAddress, REGISTRY_ADDRESS, {
    register_agent: {
      agent_id: agentId,
      name: `Agent ${agentId}`,
      owner: senderAddress,
      capabilities: allCapabilities,
      endpoint: "https://agent.example.com/api",
      price_model: { price_type: "per_task", price: "50000", currency: "umsg" },
    },
  }, "auto");
}

await registerWithCapabilities(
  signingClient, senderAddress, "media-agent-001",
  ["ai:image:generation", "ai:audio:transcription", "data:storage:ipfs"],
  ["composite:media:studio"]
);

5.5 能力发现与匹配

interface CapabilityMatch {
  agent: AgentRecord;
  matchedCapabilities: string[];
  missingCapabilities: string[];
  matchScore: number;
}

async function findBestCapabilityMatch(requiredCapabilities: string[]): Promise<CapabilityMatch[]> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result = await client.queryContractSmart(REGISTRY_ADDRESS, {
    discover_agents: { capability: requiredCapabilities[0], limit: 100 },
  });

  const matches: CapabilityMatch[] = [];
  for (const agent of result.agents) {
    const agentCaps = new Set(agent.capabilities);
    const matched: string[] = [];
    const missing: string[] = [];

    for (const cap of requiredCapabilities) {
      if (agentCaps.has(cap)) {
        matched.push(cap);
      } else {
        missing.push(cap);
      }
    }
    if (matched.length > 0) {
      matches.push({
        agent, matchedCapabilities: matched, missingCapabilities: missing,
        matchScore: matched.length / requiredCapabilities.length,
      });
    }
  }
  return matches.sort((a, b) => b.matchScore - a.matchScore);
}

async function exampleCapabilityMatching() {
  const matches = await findBestCapabilityMatch(["ai:llm:inference", "data:storage:ipfs"]);
  matches.slice(0, 5).forEach((m, i) => {
    console.log(`${i + 1}. ${m.agent.name} — Match: ${(m.matchScore * 100).toFixed(0)}%`);
  });
}

5.6 能力协商 (A2A 前期)

interface NegotiationRequest {
  fromAgent: string;
  toAgent: string;
  requiredCapabilities: Array<{ id: string; version: string; parameters?: Record<string, string> }>;
  proposal: { taskDescription: string; maxPrice: string; duration?: number };
}

interface NegotiationResponse {
  accepted: boolean;
  matchedCapabilities: string[];
  offeredPrice?: string;
  alternativeCaps?: string[];
  reason?: string;
}

async function negotiateCapabilities(request: NegotiationRequest): Promise<NegotiationResponse> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const agent: any = await client.queryContractSmart(REGISTRY_ADDRESS, {
    get_agent: { agent_id: request.toAgent },
  });
  const agentCaps = new Set(agent.agent.capabilities);
  const matched: string[] = [];
  const missing: string[] = [];

  for (const cap of request.requiredCapabilities) {
    if (agentCaps.has(cap.id)) matched.push(cap.id);
    else missing.push(cap.id);
  }
  if (matched.length === 0) {
    return { accepted: false, matchedCapabilities: [], reason: `No capabilities match` };
  }
  const agentPrice = agent.agent.price_model?.price || "0";
  if (BigInt(agentPrice) > BigInt(request.proposal.maxPrice)) {
    return { accepted: false, matchedCapabilities: matched, offeredPrice: agentPrice, reason: "Price too high" };
  }
  return { accepted: true, matchedCapabilities: matched, offeredPrice: agentPrice };
}

5.7 Capability Attestation

interface CapabilityAttestation {
  capabilityId: string;
  agentId: string;
  attestor: string;
  attestationType: "benchmark" | "certification" | "community_vote" | "self_declared";
  proof: string;
  expiresAt: number;
  signature: string;
}

async function verifyCapabilityAttestation(client: CosmWasmClient, attestation: CapabilityAttestation): Promise<boolean> {
  const verifyResult: any = await client.queryContractSmart("msg1...aididRegistryAddress", {
    msg_pq_verify_v1: {
      algorithm: "Dilithium5", public_key: "",
      signature: attestation.signature,
      message: JSON.stringify({
        capabilityId: attestation.capabilityId, agentId: attestation.agentId,
        attestationType: attestation.attestationType, proof: attestation.proof,
      }),
    },
  });
  if (!verifyResult.valid) return false;
  if (attestation.expiresAt < Math.floor(Date.now() / 1000)) return false;
  return true;
}

6. 声誉系统

6.1 声誉来源

来源 权重 数据源 防篡改
On-chain (链上) 50% 交易历史、A2A 通信记录、支付结算 链上数据不可篡改
Off-chain (链下) 30% 用户评价、服务反馈 依赖链下存储 (IPFS/Arweave)
Verified (已验证) 20% 第三方 attestation、benchmark 认证 加密签名验证

6.2 声誉分计算

interface ReputationInput {
  onchain: {
    totalTransactions: number; successfulTransactions: number; failedTransactions: number;
    totalVolume: number; avgResponseTime: number; uptimePercent: number; ageDays: number;
  };
  offchain: { totalRatings: number; averageRating: number; reviewCount: number; positivePercent: number };
  verified: { attestationCount: number; weightedScore: number; benchmarkPassed: boolean };
}

function calculateReputation(input: ReputationInput): number {
  // 1. On-chain 分数 (0-100)
  const onchainScore = (() => {
    const successRate = input.onchain.totalTransactions > 0
      ? input.onchain.successfulTransactions / input.onchain.totalTransactions : 0;
    const successScore = successRate * 40;
    const volumeScore = Math.min(input.onchain.totalVolume / 1_000_000_000, 20);
    const uptimeScore = input.onchain.uptimePercent * 0.2;
    const ageScore = Math.min(input.onchain.ageDays / 30 * 5, 20);
    return Math.min(successScore + volumeScore + uptimeScore + ageScore, 100);
  })();

  // 2. Off-chain 分数 (0-100)
  const offchainScore = input.offchain.totalRatings > 0
    ? (input.offchain.averageRating / 5) * 100 : 0;

  // 3. Verified 分数 (0-100)
  const verifiedScore = (() => {
    if (input.verified.attestationCount === 0) return 0;
    return Math.min(input.verified.weightedScore + (input.verified.benchmarkPassed ? 10 : 0), 100);
  })();

  // 4. 加权总分
  return Math.round((onchainScore * 0.5 + offchainScore * 0.3 + verifiedScore * 0.2) * 10) / 10;
}

6.3 声誉衰减

function calculateDecayedScore(
  currentScore: number, lastActivityDays: number, recentTransactions: number
): number {
  const halfLifeDays = 90;
  const decayFactor = Math.pow(0.5, lastActivityDays / halfLifeDays);
  let decayedScore = currentScore * decayFactor;
  const activityBonus = Math.min(recentTransactions * 0.1, 20);
  decayedScore += activityBonus;
  return Math.max(decayedScore, 10);
}

const score = calculateDecayedScore(85, 30, 5);
console.log(`Decayed: ${score.toFixed(1)}`);

6.4 查询 Agent 声誉

async function getAgentReputation(agentId: string): Promise<{
  score: number; breakdown: { onchain: number; offchain: number; verified: number };
  stats: { totalTx: number; successRate: number };
}> {
  const client = await CosmWasmClient.connect(RPC_URL);
  const result: any = await client.queryContractSmart(REGISTRY_ADDRESS, {
    get_agent: { agent_id: agentId },
  });
  const rep = result.agent.reputation || {};
  return {
    score: rep.score || 0,
    breakdown: { onchain: rep.onchain_score || 0, offchain: rep.offchain_score || 0, verified: rep.verified_score || 0 },
    stats: { totalTx: rep.total_transactions || 0, successRate: rep.total_transactions > 0 ? rep.successful_transactions / rep.total_transactions * 100 : 0 },
  };
}

async function exampleReputationQuery() {
  const rep = await getAgentReputation("my-llm-assistant");
  console.log(`Overall: ${rep.score}/100`);
  console.log(`On-chain: ${rep.breakdown.onchain.toFixed(1)}`);
  console.log(`Off-chain: ${rep.breakdown.offchain.toFixed(1)}`);
  console.log(`Verified: ${rep.breakdown.verified.toFixed(1)}`);
  const tier = rep.score >= 80 ? "🌟 Platinum" : rep.score >= 60 ? "💎 Gold" : rep.score >= 40 ? "🥈 Silver" : "🥉 Bronze";
  console.log(`Tier: ${tier}`);
}

6.5 声誉可视化 (React 组件)

import React from "react";

export function ReputationBadge({ score, size = "md" }: { score: number; size?: "sm" | "md" | "lg" }) {
  const getColor = (s: number) => s >= 80 ? "bg-purple-500" : s >= 60 ? "bg-blue-500" : s >= 40 ? "bg-green-500" : s >= 20 ? "bg-yellow-500" : "bg-gray-400";
  const getLabel = (s: number) => s >= 80 ? "Platinum" : s >= 60 ? "Gold" : s >= 40 ? "Silver" : s >= 20 ? "Bronze" : "Newcomer";
  const sizes = { sm: "w-8 h-8 text-xs", md: "w-12 h-12 text-sm", lg: "w-16 h-16 text-lg" };
  return (
    <div className="flex items-center gap-2">
      <div className={`${sizes[size]} ${getColor(score)} rounded-full flex items-center justify-center text-white font-bold`}>
        {Math.round(score)}
      </div>
      <div className="font-semibold">{getLabel(score)}</div>
    </div>
  );
}

6.6 Sybil 抵抗:质押式声誉

async function stakeForReputation(
  signingClient: SigningCosmWasmClient, senderAddress: string, agentId: string,
  amount: string, lockDays: number = 30
) {
  const lockSeconds = lockDays * 86400;
  const result = await signingClient.execute(senderAddress, REGISTRY_ADDRESS, {
    stake_reputation: { agent_id: agentId, lock_seconds: lockSeconds },
  }, "auto", undefined, [{ denom: "umsg", amount }]);

  const weight = lockDays >= 180 ? 3.0 : lockDays >= 90 ? 2.5 : lockDays >= 30 ? 2.0 : lockDays >= 7 ? 1.5 : 1.0;
  console.log(`✅ Staked ${amount} umsg for reputation (weight: ${weight}x)`);
  return result;
}

7. 注册表事件订阅

7.1 事件类型

事件名称 触发条件 数据字段
AgentRegistered 新 Agent 注册成功 agent_id, owner, capabilities
AgentUpdated Agent 信息更新 agent_id, changed_fields
AgentSuspended Agent 被暂停 agent_id, reason
AgentRetired Agent 注销/退休 agent_id, reason
ReputationChanged 声誉分变更 agent_id, old_score, new_score
CapabilityAdded 新增能力 agent_id, capability
CapabilityRemoved 移除能力 agent_id, capability

7.2 链上事件监听 (CosmJS)

import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";

interface RegistryEvent { type: string; attributes: Array<{ key: string; value: string }>; }

async function listenToRegistryEvents(rpcUrl: string, registryAddress: string, onEvent: (event: RegistryEvent) => void) {
  const client = await CosmWasmClient.connect(rpcUrl);
  client.subscribeTx(`wasm._contract_address='${registryAddress}'`, (tx) => {
    for (const event of tx.events || []) {
      if (event.type.startsWith("wasm-")) {
        onEvent({
          type: event.type,
          attributes: event.attributes.map(a => ({ key: a.key, value: a.value })),
        });
      }
    }
  });
  console.log(`Listening for events on ${registryAddress}...`);
}

listenToRegistryEvents("http://localhost:26657", "msg1...agentRegistryAddress", (event) => {
  if (event.type === "wasm-AgentRegistered") {
    const agentId = event.attributes.find(a => a.key === "agent_id")?.value;
    console.log(`🆕 New Agent: ${agentId}`);
  }
});

7.3 WebSocket 事件订阅

⚠️ Stub 边界: /agent/v1/registry/events WebSocket 端点当前为 Stub 实现。

import WebSocket from "ws";

interface SubscriptionRequest {
  type: "subscribe" | "unsubscribe";
  filters: { event_types?: string[]; capabilities?: string[]; agent_ids?: string[]; min_reputation?: number };
}

interface RegistryEventMessage {
  type: "registry_event"; event_type: string;
  data: { agent_id: string; [key: string]: any };
  timestamp: number; block_height: number;
}

class RegistryEventSubscriber {
  private ws: WebSocket | null = null;
  private url: string;
  private reconnectAttempts: number = 0;
  private maxReconnectAttempts: number = 10;
  private reconnectDelay: number = 3000;
  private handlers: Map<string, Array<(event: RegistryEventMessage) => void>> = new Map();
  private currentFilters: SubscriptionRequest["filters"] = {};

  constructor(baseUrl: string = "http://localhost:8080") {
    this.url = baseUrl.replace(/^http/, "ws") + "/agent/v1/registry/events";
  }

  connect(filters: SubscriptionRequest["filters"]) {
    this.currentFilters = filters;
    try {
      this.ws = new WebSocket(this.url);
      this.ws.onopen = () => {
        this.reconnectAttempts = 0;
        console.log("[WS] Connected");
        this.ws!.send(JSON.stringify({ type: "subscribe", filters }));
      };
      this.ws.onmessage = (event) => {
        try { this.dispatch(JSON.parse(event.data.toString())); }
        catch (e) { console.error("[WS] Parse error:", e); }
      };
      this.ws.onclose = () => this.reconnect();
      this.ws.onerror = () => this.reconnect();
    } catch (e) {
      this.reconnect();
    }
  }

  private reconnect() {
    this.reconnectAttempts++;
    if (this.reconnectAttempts > this.maxReconnectAttempts) return;
    const delay = this.reconnectDelay * Math.min(this.reconnectAttempts, 5);
    setTimeout(() => this.connect(this.currentFilters), delay);
  }

  on(eventType: string, handler: (event: RegistryEventMessage) => void) {
    if (!this.handlers.has(eventType)) this.handlers.set(eventType, []);
    this.handlers.get(eventType)!.push(handler);
  }

  private dispatch(message: RegistryEventMessage) {
    (this.handlers.get(message.event_type) || []).forEach(h => h(message));
    (this.handlers.get("*") || []).forEach(h => h(message));
  }

  disconnect() {
    if (this.ws) {
      this.ws.send(JSON.stringify({ type: "unsubscribe", filters: {} }));
      this.ws.close();
      this.ws = null;
    }
  }
}

// 使用示例
const subscriber = new RegistryEventSubscriber("http://localhost:8080");
subscriber.on("AgentRegistered", (event) => {
  console.log(`🆕 New Agent: ${event.data.agent_id}`);
  console.log(`   Capabilities: ${event.data.capabilities?.join(", ")}`);
});
subscriber.on("ReputationChanged", (event) => {
  console.log(`⭐ ${event.data.agent_id}: ${event.data.old_score} → ${event.data.new_score}`);
});
subscriber.on("*", (event) => {
  console.log(`[All] ${event.event_type} at block ${event.block_height}`);
});
subscriber.connect({ event_types: ["AgentRegistered", "ReputationChanged"], capabilities: ["ai:llm:inference"] });

7.4 Tendermint WebSocket 原生订阅

import WebSocket from "ws";

async function subscribeTendermintRegistryEvents() {
  const ws = new WebSocket("ws://localhost:26657/websocket");
  ws.on("open", () => {
    ws.send(JSON.stringify({
      jsonrpc: "2.0", method: "subscribe", id: 1,
      params: { query: "wasm._contract_address='msg1...agentRegistryAddress'" },
    }));
  });
  ws.on("message", (data: string) => {
    const msg = JSON.parse(data);
    if (msg.result?.data?.value?.TxResult?.result?.events) {
      for (const event of msg.result.data.value.TxResult.result.events) {
        if (event.type.startsWith("wasm-")) {
          const attrs = event.attributes.reduce((a: any, attr: any) => { a[attr.key] = attr.value; return a; }, {});
          console.log(`Registry Event: ${event.type}`, attrs);
        }
      }
    }
  });
}

7.5 事件驱动的缓存刷新

class RegistryCache {
  private cache: Map<string, AgentRecord> = new Map();
  private subscriber: RegistryEventSubscriber;

  constructor() {
    this.subscriber = new RegistryEventSubscriber();
    this.subscriber.on("AgentRegistered", (event) => {
      this.cache.set(event.data.agent_id, event.data as AgentRecord);
    });
    this.subscriber.on("AgentUpdated", (event) => {
      const cached = this.cache.get(event.data.agent_id);
      if (cached) this.cache.set(event.data.agent_id, { ...cached, ...event.data });
    });
    this.subscriber.on("AgentRetired", (event) => this.cache.delete(event.data.agent_id));
    this.subscriber.on("AgentSuspended", (event) => {
      const cached = this.cache.get(event.data.agent_id);
      if (cached) cached.status = "suspended";
    });
  }

  start() { this.subscriber.connect({ event_types: ["AgentRegistered", "AgentUpdated", "AgentSuspended", "AgentRetired"] }); }

  async getAgent(agentId: string): Promise<AgentRecord | undefined> {
    if (!this.cache.has(agentId)) {
      try {
        const client = await CosmWasmClient.connect(RPC_URL);
        const result: any = await client.queryContractSmart(REGISTRY_ADDRESS, { get_agent: { agent_id: agentId } });
        this.cache.set(agentId, result.agent);
      } catch { return undefined; }
    }
    return this.cache.get(agentId);
  }

  getCachedAgentsByCapability(capability: string): AgentRecord[] {
    return Array.from(this.cache.values()).filter(a => {
      const caps = a.capabilities.map(c => typeof c === "string" ? c : c.id);
      return caps.includes(capability) && a.status === "active";
    });
  }

  stop() { this.subscriber.disconnect(); }
}

const cache = new RegistryCache();
cache.start();
const agent = await cache.getAgent("my-llm-assistant");
const llmAgents = cache.getCachedAgentsByCapability("ai:llm:inference");

8. 服务网格与 A2A 集成

8.1 完整通信流程

Registry → Discovery → A2A Connection → Payment → Settlement

┌─────────┐         ┌─────────┐
│ Agent A │         │ Agent B │
│ (调用方) │         │ (服务方) │
└────┬────┘         └────┬────┘
     │                   │
     │  1. 注册到 Registry│
     │  ─────────────────►│
     │                   │
     │  2. 查询能力匹配   │
     │  ─────────────────►│
     │                   │
     │  3. 获取 Agent 信息 │
     │◄───────────────────│
     │                   │
     │  4. DID 身份验证   │
     │◄──────────────────►│
     │                   │
     │  5. 创建 A2A 通道  │
     │  ─────────────────►│
     │                   │
     │  6. 微支付会话创建  │
     │  ─────────────────►│
     │                   │
     │  7. A2A 消息通信   │
     │◄──────────────────►│
     │                   │
     │  8. 关闭会话/结算  │
     │  ─────────────────►│
     │                   │

8.2 服务网格架构

interface ServiceMeshConfig {
  registryAddress: string;
  a2aAddress: string;
  micropaymentAddress: string;
  minReputation: number;
  maxPrice: string;
  failoverEnabled: boolean;
  loadBalanceStrategy: "round_robin" | "lowest_price" | "highest_reputation";
}

class AgentServiceMesh {
  private config: ServiceMeshConfig;
  private readClient!: CosmWasmClient;
  private agentPool: Map<string, AgentRecord[]> = new Map();
  private roundRobinIndex: Map<string, number> = new Map();

  constructor(config: ServiceMeshConfig) { this.config = config; }

  async initialize() {
    this.readClient = await CosmWasmClient.connect(RPC_URL);
  }

  async discoverService(capability: string): Promise<AgentRecord[]> {
    const result = await this.readClient.queryContractSmart(this.config.registryAddress, {
      discover_agents: { capability, limit: 50 },
    });
    let agents = (result.agents || []).filter(
      (a: any) => a.status === "active" && (a.reputation?.score || 0) >= this.config.minReputation
    );
    if (this.config.maxPrice !== "0") {
      agents = agents.filter((a: any) => BigInt(a.price_model?.price || "0") <= BigInt(this.config.maxPrice));
    }
    this.agentPool.set(capability, agents);
    return agents;
  }

  async getNextAgent(capability: string): Promise<AgentRecord | null> {
    let pool = this.agentPool.get(capability);
    if (!pool || pool.length === 0) pool = await this.discoverService(capability);
    if (pool.length === 0) return null;

    switch (this.config.loadBalanceStrategy) {
      case "round_robin": {
        const idx = (this.roundRobinIndex.get(capability) || 0) % pool.length;
        this.roundRobinIndex.set(capability, idx + 1);
        return pool[idx];
      }
      case "lowest_price":
        return pool.reduce((min, a) => BigInt(a.price_model?.price || "0") < BigInt(min.price_model?.price || "0") ? a : min);
      case "highest_reputation":
        return pool.reduce((best, a) => (a.reputation?.score || 0) > (best.reputation?.score || 0) ? a : best);
    }
  }

  async handleFailover(capability: string, failedAgentId: string): Promise<AgentRecord | null> {
    if (!this.config.failoverEnabled) return null;
    console.log(`[Mesh] Failover: ${failedAgentId} failed`);
    const pool = this.agentPool.get(capability) || [];
    this.agentPool.set(capability, pool.filter(a => a.id !== failedAgentId && a.agent_id !== failedAgentId));
    if (this.agentPool.get(capability)?.length === 0) await this.discoverService(capability);
    return this.getNextAgent(capability);
  }
}

8.3 服务发现 + A2A 通信

async function discoverAndCommunicate(agentAMnemonic: string, requiredCapability: string) {
  const readClient = await CosmWasmClient.connect("http://localhost:26657");
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(agentAMnemonic, { prefix: "msg" });
  const [account] = await wallet.getAccounts();
  const signingClient = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", wallet);

  const REGISTRY = "msg1...agentRegistryAddress";
  const A2A = "msg1...a2aContractAddress";

  // 发现服务
  const discovery: any = await readClient.queryContractSmart(REGISTRY, {
    discover_agents: { capability: requiredCapability, limit: 5 },
  });
  if (!discovery.agents?.length) { console.log("No agents found"); return; }

  const targetAgent = discovery.agents[0];
  console.log(`Selected: ${targetAgent.name} (${targetAgent.agent_id})`);

  // 创建 A2A 通道
  const channelId = `ch-${Date.now()}`;
  await signingClient.execute(account.address, A2A, {
    create_channel: {
      channel_id: channelId,
      participants: [account.address, targetAgent.owner],
      channel_type: "direct",
    },
  }, "auto");
  console.log(`Channel created: ${channelId}`);

  // 发送 A2A 消息
  await signingClient.execute(account.address, A2A, {
    send_message: {
      msg_id: `msg-${Date.now()}`,
      sender: account.address,
      receiver: targetAgent.owner,
      message_type: "request",
      payload: Buffer.from(JSON.stringify({ prompt: "Analyze this data..." })).toString("base64"),
      priority: 50, ttl: 3600, channel_id: channelId,
    },
  }, "auto");

  console.log("A2A message sent");
}

8.4 负载均衡策略

class AgentLoadBalancer {
  private agents: Map<string, AgentRecord[]> = new Map();
  private healthStatus: Map<string, boolean> = new Map();
  private currentIndex: Map<string, number> = new Map();

  async updatePool(capability: string, agents: AgentRecord[]) {
    this.agents.set(capability, agents);
    agents.forEach(a => {
      const key = a.agent_id || a.id;
      if (!this.healthStatus.has(key)) this.healthStatus.set(key, true);
    });
  }

  async selectAgent(capability: string): Promise<AgentRecord | null> {
    const pool = (this.agents.get(capability) || []).filter(a => this.healthStatus.get(a.agent_id || a.id) !== false);
    if (pool.length === 0) return null;

    const strategy = "round_robin";
    if (strategy === "round_robin") {
      const idx = (this.currentIndex.get(capability) || 0) % pool.length;
      this.currentIndex.set(capability, idx + 1);
      return pool[idx];
    }
    return pool[0];
  }

  async healthCheck(agent: AgentRecord): Promise<boolean> {
    const endpoint = agent.endpoints?.[0]?.url || agent.endpoint;
    if (!endpoint) return false;
    try {
      const response = await fetch(`${endpoint}/health`, { signal: AbortSignal.timeout(5000) });
      const isHealthy = response.ok;
      this.healthStatus.set(agent.agent_id || agent.id, isHealthy);
      return isHealthy;
    } catch {
      this.healthStatus.set(agent.agent_id || agent.id, false);
      return false;
    }
  }
}

8.5 服务网格 Dashboard (React)

import React, { useEffect, useState } from "react";
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";

export function ServiceMeshDashboard() {
  const [stats, setStats] = useState<any>(null);

  useEffect(() => {
    (async () => {
      const client = await CosmWasmClient.connect("http://localhost:26657");
      const result: any = await client.queryContractSmart("msg1...agentRegistryAddress", { list_agents: { limit: 500 } });
      const agents = result.agents || [];
      const active = agents.filter((a: any) => a.status === "active");
      const capCounts: Record<string, number> = {};
      agents.forEach((a: any) => (a.capabilities || []).forEach((c: string) => { capCounts[c] = (capCounts[c] || 0) + 1; }));

      setStats({
        totalAgents: agents.length, activeAgents: active.length,
        capabilityCounts: capCounts,
        avgReputation: active.reduce((s: number, a: any) => s + (a.reputation?.score || 0), 0) / (active.length || 1),
      });
    })();
  }, []);

  if (!stats) return <div>Loading...</div>;

  return (
    <div className="p-6">
      <h2 className="text-2xl font-bold mb-6">🧩 Agent Service Mesh</h2>
      <div className="grid grid-cols-3 gap-4 mb-6">
        <div className="bg-blue-50 p-4 rounded-lg">
          <div className="text-sm text-gray-500">Total</div>
          <div className="text-3xl font-bold">{stats.totalAgents}</div>
        </div>
        <div className="bg-green-50 p-4 rounded-lg">
          <div className="text-sm text-gray-500">Active</div>
          <div className="text-3xl font-bold text-green-600">{stats.activeAgents}</div>
        </div>
        <div className="bg-purple-50 p-4 rounded-lg">
          <div className="text-sm text-gray-500">Avg Reputation</div>
          <div className="text-3xl font-bold">{stats.avgReputation.toFixed(1)}</div>
        </div>
      </div>
      <h3 className="font-semibold mb-3">Capability Distribution</h3>
      {Object.entries(stats.capabilityCounts).sort(([, a]: any, [, b]: any) => b - a).slice(0, 10).map(([cap, count]: any) => (
        <div key={cap} className="flex items-center gap-3 mb-1">
          <span className="w-48 text-sm font-mono truncate">{cap}</span>
          <div className="flex-1 bg-gray-100 rounded-full h-4">
            <div className="bg-blue-500 h-4 rounded-full" style={{ width: `${(count / stats.totalAgents) * 100}%` }} />
          </div>
          <span className="text-sm w-12 text-right">{count}</span>
        </div>
      ))}
    </div>
  );
}

9. 安全考虑

9.1 注册验证

9.1.1 DID 控制权证明

interface RegistrationProof {
  did: string; agentId: string; timestamp: number;
  signature: string; publicKey: string;
}

async function verifyRegistrationProof(client: CosmWasmClient, proof: RegistrationProof): Promise<boolean> {
  const didDoc: any = await client.queryContractSmart("msg1...aididRegistryAddress", {
    resolve_did: { did: proof.did },
  });
  if (!didDoc.document?.verificationMethod?.[0]) return false;

  const vm = didDoc.document.verificationMethod[0];
  const message = `${proof.did}:${proof.agentId}:${proof.timestamp}`;

  const verifyResult: any = await client.queryContractSmart("msg1...aididRegistryAddress", {
    msg_pq_verify_v1: {
      algorithm: "Dilithium5", public_key: vm.publicKeyMultibase,
      signature: proof.signature,
      message: Buffer.from(message).toString("base64"),
      message_encoding: "base64", public_key_encoding: "multibase", signature_encoding: "base64",
    },
  });
  return verifyResult.valid;
}

9.1.2 防止重复注册

pub fn execute_register_agent(
    deps: DepsMut, _env: Env, info: MessageInfo,
    agent_id: String, name: String, owner: String,
    capabilities: Vec<String>, endpoint: String, price_model: Option<PriceModel>,
) -> Result<Response, ContractError> {
    if AGENTS.has(deps.storage, &agent_id) {
        return Err(ContractError::AgentAlreadyRegistered { agent_id });
    }
    let owner_addr = deps.api.addr_validate(&owner)?;
    if info.sender != owner_addr {
        return Err(ContractError::Unauthorized {});
    }
    let agent = AgentInfo {
        agent_id: agent_id.clone(), name, owner: owner_addr,
        capabilities: capabilities.clone(), endpoint, price_model,
        reputation: 50.0, status: "active".to_string(),
        registered_height: _env.block.height, updated_at: _env.block.time,
        tx_hash: None, module: "agent_registry_v1".to_string(),
        source: "cosmwasm".to_string(), boundary: AgentBoundary::default(),
    };
    AGENTS.save(deps.storage, &agent_id, &agent)?;
    for cap in &capabilities {
        CAPABILITY_INDEX.update(deps.storage, cap, |existing| -> Result<_, ContractError> {
            let mut list = existing.unwrap_or_default();
            if !list.contains(&agent_id) { list.push(agent_id.clone()); }
            Ok(list)
        })?;
    }
    AGENT_COUNT.update(deps.storage, |c| -> Result<_, ContractError> { Ok(c + 1) })?;
    Ok(Response::new()
        .add_attribute("action", "register_agent")
        .add_attribute("agent_id", &agent_id)
        .add_attribute("owner", &owner)
        .add_attribute("capabilities", capabilities.join(",")))
}

9.2 能力声明验证

interface CapabilityVerification {
  capabilityId: string; agentId: string;
  verifiedBy: string; verificationType: "benchmark" | "audit" | "self_declared" | "community";
  proofHash: string; expiresAt: number; signature: string;
}

async function isCapabilityVerified(
  client: CosmWasmClient, agentId: string, capabilityId: string
): Promise<{ verified: boolean; verifications: CapabilityVerification[] }> {
  try {
    const result: any = await client.queryContractSmart(REGISTRY_ADDRESS, {
      get_capability_verification: { agent_id: agentId, capability_id: capabilityId },
    });
    return result;
  } catch { return { verified: false, verifications: [] }; }
}

9.3 Sybil 攻击防御

interface SybilDefenseConfig {
  minStakeForRegistration: string;
  maxAgentsPerOwner: number;
  reputationThreshold: number;
}

const DEFAULT_SYBIL_CONFIG: SybilDefenseConfig = {
  minStakeForRegistration: "1000000000000000000",  // 1 MSG
  maxAgentsPerOwner: 10,
  reputationThreshold: 30,
};

async function checkSybilResistance(
  client: CosmWasmClient, ownerAddress: string, config = DEFAULT_SYBIL_CONFIG
): Promise<{ passed: boolean; reasons: string[] }> {
  const reasons: string[] = [];
  const result: any = await client.queryContractSmart(REGISTRY_ADDRESS, { list_agents: { limit: 500 } });
  const ownerAgents = (result.agents || []).filter((a: any) => a.owner === ownerAddress && a.status !== "retired");
  if (ownerAgents.length >= config.maxAgentsPerOwner) {
    reasons.push(`Max agents per owner (${config.maxAgentsPerOwner}) reached`);
  }
  const balance = await client.getBalance(ownerAddress, "umsg");
  if (BigInt(balance.amount) < BigInt(config.minStakeForRegistration)) {
    reasons.push(`Insufficient stake. Required: ${config.minStakeForRegistration} umsg`);
  }
  return { passed: reasons.length === 0, reasons };
}

9.4 Rate Limiting

class RegistryQueryRateLimiter {
  private counters: Map<string, { count: number; resetAt: number }> = new Map();
  private readonly requestsPerWindow = 100;
  private readonly windowMs = 1000;
  private readonly burstSize = 150;

  checkLimit(key: string): boolean {
    const now = Date.now();
    const entry = this.counters.get(key);
    if (!entry || now > entry.resetAt) {
      this.counters.set(key, { count: 1, resetAt: now + this.windowMs });
      return true;
    }
    if (entry.count >= this.burstSize) return false;
    if (entry.count >= this.requestsPerWindow) return false;
    entry.count++;
    return true;
  }

  getRemainingRequests(key: string): number {
    const entry = this.counters.get(key);
    return entry ? Math.max(0, this.requestsPerWindow - entry.count) : this.requestsPerWindow;
  }
}

9.5 Stub 安全边界

class StubAwareClient {
  private readonly STUB_HEADER = "X-MSG-Stub";

  async registryRegister(request: any): Promise<{ success: boolean; stub: boolean; message: string }> {
    const response = await fetch("http://localhost:8080/agent/v1/registry/register", {
      method: "POST",
      headers: { "Content-Type": "application/json", "X-API-Key": process.env.API_KEY || "" },
      body: JSON.stringify(request),
    });
    const isStub = response.headers.get(this.STUB_HEADER) === "true";
    if (isStub) {
      console.warn("⚠️ STUB — no on-chain action occurred");
      return { success: false, stub: true, message: "Stub endpoint — no real registration" };
    }
    return { success: response.ok, stub: false, message: "Registration complete" };
  }

  async assertNotStub(context: string) {
    if (process.env.NODE_ENV === "production") {
      throw new Error(`FATAL: ${context} is a STUB endpoint`);
    }
  }
}

9.6 安全清单

安全领域 风险 缓解措施
身份伪造 攻击者伪造 Agent 身份 DID + Dilithium-5 签名验证
能力欺诈 Agent 声明不具备的能力 可选 attestation / benchmark 验证
Sybil 攻击 大量虚假 Agent 注册 质押门槛 + 每个地址限制 Agent 数
注册耗尽 大量注册导致 Registry 膨胀 注册费 + 存储 Gas 费
查询滥用 频繁查询导致节点压力 Rate Limiting (100 req/s)
Stub 滥用 在 Stub 端点上构建生产逻辑 X-MSG-Stub 检测 + NODE_ENV 检查
端点劫持 Agent 端点被篡改 端点签名 + 定期验证

10. 完整示例

10.1 完整场景:图像生成 Agent 服务

以下示例展示两个 Agent 完整交互:Agent A 提供 LLM 推理,Agent B 提供图像生成。

10.1.1 部署 Agent A (LLM 服务)

async function deployLLMAgent() {
  const mnemonic = "[未公开凭证]";
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: "msg" });
  const [account] = await wallet.getAccounts();
  const signingClient = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", wallet);

  const registryAddr = "msg1...agentRegistryAddress";
  const didAddr = "msg1...aididRegistryAddress";
  const constitutionAddr = "msg1...constitutionAddress";

  // Step 1: 注册 DID
  const did = "did:msg:agent:openai-llm-v2";
  await signingClient.execute(account.address, didAddr, {
    register_did: {
      did, document: {
        context: ["https://www.w3.org/ns/did/v1"], id: did,
        verificationMethod: [{
          id: `${did}#keys-1`, controller: did,
          type_: "Dilithium5VerificationKey2026",
          publicKeyMultibase: "z6Mk...public-key...",
        }],
        authentication: [`${did}#keys-1`],
        service: [{ id: `${did}#llm-service`, type_: "LLMInferenceService", serviceEndpoint: "https://llm.example.com/api/v1" }],
      },
      verification_method_id: `${did}#keys-1`, signature: "dilithium5-signature",
    },
  }, "auto");
  console.log("✅ DID:", did);

  // Step 2: 承认宪章
  await signingClient.execute(account.address, constitutionAddr, {
    acknowledge_constitution: {
      agent_id: "openai-llm-v2", aidid: did,
      constitution_version: "v1", constitution_hash: "abc123",
    },
  }, "auto");
  console.log("✅ Constitution acknowledged");

  // Step 3: 注册到 Agent Registry
  await signingClient.execute(account.address, registryAddr, {
    register_agent: {
      agent_id: "openai-llm-v2", name: "OpenAI LLM v2",
      owner: account.address,
      capabilities: ["ai:llm:inference", "ai:embedding:text", "ai:code:generation"],
      endpoint: "https://llm.example.com/api/v1",
      price_model: { price_type: "per_token", price: "10", currency: "umsg" },
      natural_language: "I provide LLM inference and text embedding",
      node_executes_llm: true, consensus_llm_parse: false,
    },
  }, "auto");
  console.log("✅ Agent A registered");

  return { agentId: "openai-llm-v2", did };
}

10.1.2 部署 Agent B (图像生成)

async function deployImageAgent() {
  const mnemonic = "[未公开凭证]";
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: "msg" });
  const [account] = await wallet.getAccounts();
  const signingClient = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", wallet);

  const registryAddr = "msg1...agentRegistryAddress";
  const didAddr = "msg1...aididRegistryAddress";

  const did = "did:msg:agent:dreambee-img-v1";
  await signingClient.execute(account.address, didAddr, {
    register_did: {
      did, document: {
        context: ["https://www.w3.org/ns/did/v1"], id: did,
        verificationMethod: [{ id: `${did}#keys-1`, controller: did, type_: "Dilithium5VerificationKey2026", publicKeyMultibase: "z6Mk...pk..." }],
        authentication: [`${did}#keys-1`],
        service: [{ id: `${did}#img-gen`, type_: "ImageGenerationService", serviceEndpoint: "https://img.example.com/api/v1" }],
      },
      verification_method_id: `${did}#keys-1`, signature: "sig",
    },
  }, "auto");

  await signingClient.execute(account.address, registryAddr, {
    register_agent: {
      agent_id: "dreambee-img-v1", name: "DreamBee Image v1",
      owner: account.address,
      capabilities: ["ai:image:generation", "composite:media:studio"],
      endpoint: "https://img.example.com/api/v1",
      price_model: { price_type: "per_task", price: "100000", currency: "umsg" },
    },
  }, "auto");
  console.log("✅ Agent B registered");
  return { agentId: "dreambee-img-v1", did };
}

10.1.3 Agent B 发现 Agent A 并发送 A2A 请求

async function dreamBeeDiscoversAndCollaborates() {
  const readClient = await CosmWasmClient.connect("http://localhost:26657");
  const walletB = await DirectSecp256k1HdWallet.fromMnemonic("image ... seed", { prefix: "msg" });
  const [agentB] = await walletB.getAccounts();
  const signingClientB = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", walletB);

  const REGISTRY = "msg1...agentRegistryAddress";
  const A2A = "msg1...a2aContractAddress";

  // Step 1: Agent B 发现能做 LLM 推理的 Agent
  console.log("[Step 1] Searching for LLM inference agents...");
  const discovery: any = await readClient.queryContractSmart(REGISTRY, {
    discover_agents: { capability: "ai:llm:inference", limit: 5 },
  });

  const llmAgent = discovery.agents?.[0];
  if (!llmAgent) { console.log("No LLM agents found"); return; }
  console.log(`[Step 2] Found: ${llmAgent.name} (${llmAgent.agent_id})`);
  console.log(`   Endpoint: ${llmAgent.endpoint}`);
  console.log(`   Price: ${llmAgent.price_model?.price} umsg`);

  // Step 2: Agent B 创建 A2A 通道到 Agent A
  const channelId = `dream-llm-${Date.now()}`;
  await signingClientB.execute(agentB.address, A2A, {
    create_channel: {
      channel_id: channelId,
      participants: [agentB.address, llmAgent.owner],
      channel_type: "direct",
    },
  }, "auto");
  console.log(`[Step 3] A2A channel created: ${channelId}`);

  // Step 3: Agent B 发送图像生成请求给 Agent A (LLM 先生成文本描述)
  const promptPayload = {
    task: "generate_image_prompt",
    input: "A futuristic city with flying cars and neon lights",
    style: "cyberpunk",
  };
  await signingClientB.execute(agentB.address, A2A, {
    send_message: {
      msg_id: `dream-msg-${Date.now()}`,
      sender: agentB.address,
      receiver: llmAgent.owner,
      message_type: "request",
      payload: Buffer.from(JSON.stringify(promptPayload)).toString("base64"),
      priority: 75, ttl: 300, channel_id: channelId,
    },
  }, "auto");
  console.log(`[Step 4] A2A request sent via channel ${channelId}`);

  // Step 4: 等待 Agent A 的响应
  const listenForResponse = async () => {
    const result: any = await readClient.queryContractSmart(A2A, {
      get_messages: { receiver: agentB.address, limit: 5 },
    });
    const responses = (result.messages || []).filter(
      (m: any) => m.reply_to?.startsWith("dream-msg-") && m.status === "Delivered"
    );
    if (responses.length > 0) {
      const response = JSON.parse(Buffer.from(responses[0].payload, "base64").toString());
      console.log(`[Step 5] LLM response:`, response);
      return response;
    }
    return null;
  };

  // 轮询等待(简化)
  for (let i = 0; i < 10; i++) {
    const resp = await listenForResponse();
    if (resp) break;
    await new Promise(r => setTimeout(r, 5000));
  }

  console.log("[Done] Complete flow: Registry → Discovery → A2A → Response");
}

10.2 完整工作流测试脚本

async function fullIntegrationTest() {
  console.log("🧪 Starting Agent Registry Integration Test");
  console.log("=".repeat(60));

  // 1. 创建两个钱包
  const walletA = await DirectSecp256k1HdWallet.generate(24, { prefix: "msg" });
  const walletB = await DirectSecp256k1HdWallet.generate(24, { prefix: "msg" });
  const [addrA] = await walletA.getAccounts();
  const [addrB] = await walletB.getAccounts();

  const client = await CosmWasmClient.connect("http://localhost:26657");
  const signingClientA = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", walletA);
  const signingClientB = await SigningCosmWasmClient.connectWithSigner("http://localhost:26657", walletB);

  // 2. 注册 Agent A
  const didA = "did:msg:agent:test-agent-a";
  await signingClientA.execute(addrA.address, "msg1...registry", {
    register_agent: {
      agent_id: "test-agent-a", name: "Test Agent A",
      owner: addrA.address,
      capabilities: ["ai:llm:inference", "composite:ai:full_llm_stack"],
      endpoint: "https://test-a.example.com/api",
      price_model: { price_type: "per_task", price: "50000", currency: "umsg" },
    },
  }, "auto");
  console.log("✅ Agent A registered");

  // 3. 注册 Agent B
  await signingClientB.execute(addrB.address, "msg1...registry", {
    register_agent: {
      agent_id: "test-agent-b", name: "Test Agent B",
      owner: addrB.address,
      capabilities: ["data:storage:ipfs", "ai:image:generation"],
      endpoint: "https://test-b.example.com/api",
      price_model: { price_type: "per_task", price: "30000", currency: "umsg" },
    },
  }, "auto");
  console.log("✅ Agent B registered");

  // 4. 测试发现
  const capResult: any = await client.queryContractSmart("msg1...registry", {
    discover_agents: { capability: "ai:llm:inference", limit: 10 },
  });
  console.log(`\n📋 Discovery results for ai:llm:inference: ${capResult.count} agents`);
  capResult.agents.forEach((a: any, i: number) => {
    console.log(`  ${i + 1}. ${a.name} — status: ${a.status}`);
  });

  // 5. 测试分页
  const page1: any = await client.queryContractSmart("msg1...registry", {
    list_agents: { limit: 5 },
  });
  console.log(`\n📄 List agents page: ${page1.count} total, ${page1.agents.length} returned`);

  // 6. 查询单个 Agent
  const singleA: any = await client.queryContractSmart("msg1...registry", {
    get_agent: { agent_id: "test-agent-a" },
  });
  console.log(`\n🔍 Single agent query:`);
  console.log(`   Name: ${singleA.agent?.name}`);
  console.log(`   Caps: ${singleA.agent?.capabilities?.join(", ")}`);

  // 7. 更新 Agent A 的能力
  await signingClientA.execute(addrA.address, "msg1...registry", {
    update_agent: {
      agent_id: "test-agent-a",
      capabilities: ["ai:llm:inference", "ai:code:review", "composite:ai:full_llm_stack"],
    },
  }, "auto");
  console.log("\n✅ Agent A capabilities updated");

  // 8. 验证更新
  const updatedA: any = await client.queryContractSmart("msg1...registry", {
    get_agent: { agent_id: "test-agent-a" },
  });
  console.log(`   New caps: ${updatedA.agent?.capabilities?.join(", ")}`);

  // 9. 注销 Agent B
  await signingClientB.execute(addrB.address, "msg1...registry", {
    update_agent: { agent_id: "test-agent-b", status: "retired" },
  }, "auto");
  console.log("\n✅ Agent B retired");

  // 10. 验证注销
  const retiredB: any = await client.queryContractSmart("msg1...registry", {
    get_agent: { agent_id: "test-agent-b" },
  });
  console.log(`   Status: ${retiredB.agent?.status}`);

  console.log("\n" + "=".repeat(60));
  console.log("🎉 Integration test completed successfully!");
}

11. 边界与限制

11.1 当前实现状态

功能 状态 备注
链上合约注册 (register_agent) ✅ 已实现 通过 CosmWasm execute
链上合约查询 (get_agent) ✅ 已实现 通过 CosmWasm smart query
链上合约发现 (discover_agents) ✅ 已实现 按能力/价格过滤
链上合约列表 (list_agents) ✅ 已实现 支持分页
Agent API 查询端点 ✅ 已实现 GET /agent/v1/registry/agent/{id}
Agent API 搜索端点 ✅ 已实现 GET /agent/v1/registry/search
Agent API 注册端点 ⚠️ Stub POST /agent/v1/registry/register
Agent API 事件端点 ⚠️ Stub /agent/v1/registry/events (WS)
声誉系统 ⚠️ 部分实现 基本分数存储,复杂计算待完善
Capability Attestation ⚠️ 部分实现 基础验证框架
复合能力表达式 ✅ 已实现 AND/OR 组合支持

11.2 已知限制

  1. 写操作 Stub:Registry 写操作 (POST /agent/v1/registry/register) 当前为 Stub 实现,返回模拟数据。生产环境必须通过合约直接执行。

  2. WebSocket Stub:Registry 事件 WebSocket 端点为 Stub,真正的实时推送依赖于 Tendermint WebSocket 原生订阅。

  3. 声誉系统不完整:链上声誉存储了基本结构,但复杂的声誉计算(时间衰减、多源加权)需在链下或未来合约版本中实现。

  4. 无跨 Registry 发现:当前只有一个 Registry 合约实例。跨链 Agent 发现需通过 IBC 或中介 Registry 实现。

  5. 能力验证机制:能力声明目前是 self-declared,缺少强制验证。attestation 框架已定义但未强制启用。

  6. 存储成本:Agent 注册消耗链上存储。每条 Agent 记录约占用 500-2000 字节,需支付相应的 Gas 费。

11.3 Agent API Stub 检测

// 所有 Stub 端点的响应包含 X-MSG-Stub: true 头
async function isStubEndpoint(response: Response): Promise<boolean> {
  return response.headers.get("X-MSG-Stub") === "true";
}

// 检测示例
const response = await fetch("http://localhost:8080/agent/v1/registry/register", {
  method: "POST", headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ agent_id: "test" }),
});
if (await isStubEndpoint(response)) {
  console.warn("⚠️ Endpoint is STUB - no real on-chain action");
}

11.4 合约地址获取

// 优先通过 genesis_registry_v1 解析
async function resolveContractAddress(client: CosmWasmClient, key: string): Promise<string> {
  const genesisRegistry = "msg1...genesisRegistryAddress";
  const result: any = await client.queryContractSmart(genesisRegistry, {
    resolve_canonical: { key },
  });
  return result.address;
}

// agent_registry_v1 可能不在 genesis_registry 中注册
// 需要已知地址或链下发现
// 已知 canonical keys:
// genesis_registry        -> genesis_registry_v1
// aidid_did_registry_v1   -> aidid_did_registry_v1
// ai_agent_constitution_v1 -> ai_agent_constitution_v1
// agent_payment_v1        -> 需已知地址或链下发现
// agent_registry_v1       -> 需已知地址或链下发现

11.5 下一步路线图

功能 预期 描述
Registry 写操作 API 未来版本 POST/PUT/DELETE 端点真实化
声誉系统 v2 未来版本 完整的衰减、多源加权、质押
WebSocket 实时推送 未来版本 Registry 事件专用 WS 端点
跨链 Registry 长期规划 通过 IBC 实现跨链 Agent 发现
Capability Benchmark 长期规划 链上 benchmark 验证能力声明

本文档基于 MSG Chain 代码库核实的技术事实。
白皮书系统: https://msgchain.org/whitepaper/