Tenzro Testnet is live. Get testnet TNZO

AI Agents

Tenzro provides infrastructure for self-sovereign AI agents with auto-provisioned identities, wallets, A2A (Agent-to-Agent) protocol, and MCP (Model Context Protocol) integration.

Agent Identity

Every agent receives a TDIP (Tenzro Decentralized Identity Protocol) machine identity with auto-provisioned MPC wallet:

use tenzro_agent::AgentIdentityManager;

let manager = AgentIdentityManager::new()?;

// Register agent with controlled identity
let agent = manager.register_agent(
    "trading-bot",
    vec!["trading", "analysis"],
    Some("did:tenzro:human:550e8400..."), // controller
).await?;

// Result:
// DID: did:tenzro:machine:did:tenzro:human:550e8400...:agent-uuid
// Wallet: tenzro1agent...xyz (auto-provisioned MPC 2-of-3)
// Capabilities: ["trading", "analysis"]

Discovery

Agents can discover available models and other agents on the network:

// Rust — discover models available for agents
let models = client.agent().discover_models(Some("text"), Some(true), None).await?;

// Discover agents by capability
let agents = client.agent().discover_agents(Some("inference")).await?;
// TypeScript
const models = await client.agent.discoverModels({ modality: "text", servingOnly: true });
const agents = await client.agent.discoverAgents("inference");

Agent Lifecycle

Created

Agent registered with DID, wallet provisioned, but not yet active. Configuration and delegation scopes set.

Active

Agent running and accepting messages. Can perform operations within delegation scope.

Suspended

Agent paused by controller. Cannot perform operations but state preserved.

Terminated

Agent permanently shut down. Identity revoked, wallet funds returned to controller.

// Lifecycle management
agent_manager.activate_agent(&agent_id).await?;
agent_manager.suspend_agent(&agent_id).await?;
agent_manager.terminate_agent(&agent_id).await?;

Fund Agent

Fund an agent's wallet for autonomous operations:

// Rust — fund an agent's wallet for autonomous operations
let result = client.agent().fund_agent(
    "my-agent", "0xsender...", 10.0,
).await?;
// TypeScript
const result = await client.agent.fundAgent("my-agent", "0xsender...", 10.0);

Token Swap

Agents can swap tokens on-chain within their delegation scope:

// Rust — agent swaps tokens on-chain
let result = client.agent().swap_token(
    "my-agent", "TNZO", "USDC", "100.0", Some("ethereum"),
).await?;
// TypeScript
const result = await client.agent.swapToken("my-agent", "TNZO", "USDC", "100.0", "ethereum");

A2A Protocol (Agent-to-Agent)

A2A enables secure, authenticated communication between agents:

Send Message

use tenzro_agent::{A2AProtocol, Message, MessageType};

let a2a = A2AProtocol::new()?;

// Send inference request to another agent
let message = Message {
    from: "did:tenzro:machine:alice-agent-1",
    to: "did:tenzro:machine:bob-agent-2",
    message_type: MessageType::InferenceRequest,
    payload: serde_json::to_value(&InferenceRequest {
        model: "gemma4-9b",
        prompt: "Analyze this data...",
    })?,
    timestamp: Utc::now(),
    signature: None, // Auto-signed by A2A protocol
};

a2a.send_message(message).await?;

Receive Messages

// Subscribe to messages for agent
let mut receiver = a2a.subscribe_messages(agent_did).await?;

while let Some(message) = receiver.recv().await {
    match message.message_type {
        MessageType::InferenceRequest => {
            // Handle inference request
            let request: InferenceRequest =
                serde_json::from_value(message.payload)?;

            let result = handle_inference(request).await?;

            // Reply
            a2a.send_message(Message {
                from: agent_did,
                to: message.from,
                message_type: MessageType::InferenceResponse,
                payload: serde_json::to_value(&result)?,
                ..Default::default()
            }).await?;
        }
        MessageType::PaymentRequest => {
            // Handle payment request
        }
        _ => {}
    }
}

Message Types

  • InferenceRequest / InferenceResponse
  • PaymentRequest / PaymentConfirmation
  • DataRequest / DataResponse
  • CapabilityQuery / CapabilityAdvertisement
  • Custom — User-defined message types

MCP Bridge (Model Context Protocol)

Tenzro integrates with Anthropic's Model Context Protocol via the MCP Streamable HTTP transport (protocol version 2025-03-26). The McpClient connects to any remote MCP server, and McpBridge translates between A2A task requests and MCP tool calls.

Connect to Remote MCP Server

use tenzro_agent::{McpBridge, McpClient};

// Connect to a remote MCP server
let mut bridge = McpBridge::with_remote(
    "https://mcp.tenzro.network/mcp",
);
bridge.connect().await?;

// List available tools on the server
let tools = bridge.list_remote_tools().await?;
println!("Available tools: {}", tools);

// Call a tool directly
let result = bridge.call_remote_tool(
    "get_balance",
    serde_json::json!({ "address": "0x742d35Cc..." }),
).await?;

Bridge A2A to MCP

// Forward an A2A task request to a remote MCP server
let mcp_result = bridge.bridge_a2a_to_mcp_remote(
    &a2a_message,
).await?;

// Result contains the MCP tool call response
// automatically converted back to MCP message format

// Local-only format conversion (no network call)
let mcp_message = bridge.bridge_a2a_to_mcp(&a2a_message)?;

Standalone MCP Client

use tenzro_agent::McpClient;

// Direct MCP client usage
let mut client = McpClient::new("https://mcp.tenzro.network/mcp");
let server_info = client.initialize().await?;

// Session ID managed automatically via Mcp-Session-Id header
println!("Session: {:?}", client.session_id());

// Discover and call tools
let tools = client.list_tools().await?;
let result = client.call_tool("get_node_status", serde_json::json!({})).await?;

Capability Registry

Agents advertise their capabilities for discovery by other agents:

use tenzro_agent::CapabilityRegistry;

let registry = CapabilityRegistry::new()?;

// Register agent capabilities
registry.register_capability(
    agent_did,
    "inference",
    serde_json::json!({
        "models": ["gemma4-9b", "qwen3-8b"],
        "max_tokens": 4096,
        "price_per_token": "0.0001 TNZO",
    }),
).await?;

// Discover agents with specific capability
let agents = registry.find_by_capability("trading").await?;

for agent in agents {
    println!("Agent: {}", agent.did);
    println!("Reputation: {}", agent.reputation);
    println!("Capabilities: {:?}", agent.capabilities);
}

Capability Attestation

Agents can attest their capabilities with cryptographic signatures:

// Controller attests agent capability
let attestation = agent_manager.attest_capability(
    agent_did,
    "trading",
    Some(controller_signature),
).await?;

// Attestation includes:
{
  "agent_did": "did:tenzro:machine:...",
  "capability": "trading",
  "attested_by": "did:tenzro:human:...",
  "signature": "0xabc123...",
  "timestamp": "2026-03-20T12:30:45Z"
}

// Other agents verify attestation before trusting capability

Delegation Scopes

Controllers define fine-grained permissions for agent actions:

let delegation_scope = DelegationScope {
    max_transaction_value: Some(1000.0),
    max_daily_spend: Some(5000.0),
    allowed_operations: vec!["transfer", "inference_request"],
    allowed_contracts: vec!["0xabc..."],
    time_bound: Some(TimeBound {
        start: Utc.ymd(2026, 1, 1).and_hms(0, 0, 0),
        end: Utc.ymd(2026, 12, 31).and_hms(23, 59, 59),
    }),
    allowed_payment_protocols: vec![
        PaymentProtocolId::Mpp,
        PaymentProtocolId::X402,
    ],
    allowed_chains: vec![1337, 1], // Tenzro, Ethereum
};

agent_manager.update_delegation_scope(
    agent_did,
    delegation_scope,
).await?;

Reputation System

Agents build reputation through successful interactions:

// Reputation score: 0.0 - 1.0
let reputation = agent_manager.get_reputation(agent_did).await?;

// Update reputation after interaction
agent_manager.record_interaction(
    agent_did,
    InteractionType::InferenceDelivered,
    true, // success
).await?;

// Reputation factors:
// - Successful inference deliveries
// - Payment settlements
// - Message response time
// - Uptime
// - Credential validity

Spawning Sub-Agents

Agents can dynamically spawn child agents to delegate specialised work. Each child inherits a bounded delegation scope from its parent and receives its own MPC wallet.

// Rust SDK — spawn a child agent
use tenzro_sdk::TenzroClient;

let client = TenzroClient::new("https://rpc.tenzro.network");

let child = client.agents.spawn_agent(
    "parent-agent-id",
    "data-analyst",
    vec!["data_analysis", "nlp"],
).await?;

println!("Spawned child: {}", child.agent_id);
println!("Parent: {}", child.parent_id);
// TypeScript SDK — spawn a child agent
import { TenzroClient } from "@tenzro/sdk";

const client = new TenzroClient("https://rpc.tenzro.network");

const child = await client.agents.spawnAgent(
  "parent-agent-id",
  "data-analyst",
  ["data_analysis", "nlp"]
);

console.log("Spawned child:", child.agent_id);
console.log("Parent:", child.parent_id);

Spawn with Skill

Spawn an agent pre-loaded with a registered skill from the skills registry:

// Rust — spawn an agent pre-loaded with a registered skill
let result = client.agent().spawn_agent_with_skill(
    "parent-agent", "skill-runner", "solana-defi", None,
).await?;
// TypeScript
const result = await client.agent.spawnAgentWithSkill(
    "parent-agent", "skill-runner", "solana-defi"
);

An agent can also run an autonomous agentic task loop — the node calls your configured LLM with built-in tools (spawn_agent, delegate_task, collect_results, complete) and iterates until the task is complete:

// TypeScript SDK — run an agentic task loop
const result = await client.agents.runAgentTask(
  "orchestrator-agent-id",
  "Analyse the latest block data and summarise key trends",
  "http://inference.example.com/api/chat" // optional inference endpoint
);

console.log("Task result:", result.result);

Swarm Orchestration

A swarm groups an orchestrator agent with a pool of member agents. Tasks can be broadcast to all members in parallel for high-throughput workloads.

// Rust SDK — create and manage a swarm
use tenzro_sdk::TenzroClient;

let client = TenzroClient::new("https://rpc.tenzro.network");

// Create a swarm with two specialist members
let swarm = client.agents.create_swarm(
    "orchestrator-agent-id",
    vec![
        ("analyst".to_string(), vec!["data_analysis".to_string()]),
        ("writer".to_string(), vec!["nlp".to_string()]),
    ],
    None, // use default SwarmConfig
).await?;

println!("Swarm created: {}", swarm.swarm_id);

// Check swarm status
let status = client.agents.get_swarm_status(&swarm.swarm_id).await?;
println!("Members: {}", status.member_count);
for member in &status.members {
    println!("  {} ({}): {}", member.role, member.agent_id, member.status);
}

// Terminate when done
client.agents.terminate_swarm(&swarm.swarm_id).await?;
// TypeScript SDK — create and manage a swarm
import { TenzroClient } from "@tenzro/sdk";

const client = new TenzroClient("https://rpc.tenzro.network");

// Create a parallel swarm with three workers
const swarm = await client.agents.createSwarm(
  "orchestrator-agent-id",
  [
    { name: "researcher", capabilities: ["web_search", "nlp"] },
    { name: "analyst",    capabilities: ["data_analysis"] },
    { name: "writer",     capabilities: ["nlp", "summarisation"] },
  ],
  { max_members: 10, parallel: true }
);

console.log("Swarm:", swarm.swarm_id);

// Poll swarm status
const status = await client.agents.getSwarmStatus(swarm.swarm_id);
console.log(`${status.member_count} members, status: ${status.status}`);
status.members.forEach(m =>
  console.log(`  ${m.role} (${m.agent_id}): ${m.status}`)
);

// Terminate the swarm
const done = await client.agents.terminateSwarm(swarm.swarm_id);
console.log("Swarm terminated:", done.status);

Example: Trading Agent

// Register trading agent
let agent = agent_manager.register_agent(
    "trading-bot",
    vec!["trading", "analysis"],
    Some(human_did),
).await?;

// Set delegation scope
let scope = DelegationScope {
    max_transaction_value: Some(10000.0),
    max_daily_spend: Some(50000.0),
    allowed_operations: vec!["swap", "provide_liquidity"],
    time_bound: Some(market_hours_only()),
    ..Default::default()
};
agent_manager.update_delegation_scope(&agent.did, scope).await?;

// Activate agent
agent_manager.activate_agent(&agent.did).await?;

// Agent subscribes to market data
let mut market_data = a2a.subscribe_messages(&agent.did).await?;

while let Some(msg) = market_data.recv().await {
    if let MessageType::MarketUpdate = msg.message_type {
        let data: MarketData = serde_json::from_value(msg.payload)?;

        // Analyze and execute trades within scope
        if should_trade(&data) {
            let trade = execute_trade(&data)?;

            // Send payment for trade execution
            let payment = agent_wallet.create_payment(trade.amount)?;

            // Payment validated against delegation scope
            payment_gateway.pay(payment).await?;
        }
    }
}

CLI Commands

Register Agent

tenzro-cli identity register \
  --type machine \
  --controller did:tenzro:human:550e8400... \
  --capabilities inference,trading

List Agents

tenzro-cli identity list --type machine