Tenzro Testnet is live —request testnet TNZO
← Back to Tutorials

Build a Portfolio Rebalancer Agent

AI AgentsAdvanced20 min

A portfolio rebalancer watches a set of asset weights, compares them against a target allocation, and submits trades whenever the drift exceeds tolerance. On Tenzro you can deploy the entire agent without writing any Rust code — the AgentKit template ref-yield-rebalancer-v1 encodes the identity provisioning, delegation scope, drift calculation, and trade dispatch declaratively. You configure it, spawn it, and run it from the tenzro CLI.

What You'll Do

  • Explore the ref-yield-rebalancer-v1 AgentKit template
  • Spawn a rebalancer agent with a 7-day time-bound delegation scope and hard spend caps
  • Dry-run the agent against simulated prices to verify drift calculations
  • Execute a live rebalance run with real on-chain trades
  • Review results including delegation enforcement and trade receipts

Why Delegation-First Trading Matters

The whole point of running an autonomous trading agent is that you don't want to babysit it. But that means the security boundary needs to be the delegation scope, not your own monitoring. On Tenzro every machine identity is provisioned under a controller identity, and the controller installs a DelegationScopethat hard-caps per-transaction value, daily spend, allowed operations, and a time bound. The agent never gets a wallet without one of these scopes attached. The pattern is: compute the trade, ask the registry whether it's authorized, and only then dispatch it through the EVM. If the answer is no, the trade is silently dropped — no on-chain footprint, no wasted gas.

Step 1: Prerequisites

You need the tenzro installed and a running node to connect to. If you haven't already joined the network, do that first — tenzro join provisions your identity and wallet in a single command:

# Install the CLI (if not already installed)
cargo install --path crates/tenzro-cli

# Join the network  provisions your human identity + MPC wallet
tenzro join

# Verify your wallet is funded (request testnet tokens if needed)
tenzro wallet balance

You should see your controller DID (format did:tenzro:human:...) and a wallet balance. If you need testnet TNZO, hit the faucet:

curl -X POST https://api.tenzro.network/faucet \
  -H "Content-Type: application/json" \
  -d '{"address": "<your-wallet-address>"}'

Step 2: Explore the Yield-Rebalancer Template

AgentKit ships pre-built agent templates. Start by listing what's available, then inspect the rebalancer template to understand its configuration surface:

# List all available AgentKit templates
tenzro agent list-templates

You'll see ref-yield-rebalancer-v1 in the output. Pull its full specification:

# Inspect the rebalancer template
tenzro agent get-template ref-yield-rebalancer-v1

The output shows every configurable parameter:

Template: ref-yield-rebalancer-v1
Description: Autonomous portfolio rebalancer with delegation-gated trades

Parameters:
  assets              List of asset symbols and target weights (bps)
  max_transaction     Per-trade cap in TNZO (delegation enforced)
  max_daily_spend     Daily spend cap in TNZO (delegation enforced)
  drift_threshold     Minimum drift in bps before rebalancing (default: 100)
  allowed_operations  Whitelisted operations (default: rebalance, trade)
  scope_duration_days Time bound for delegation scope (default: 7)
  price_source        Price oracle source (default: on-chain)

Identity:
  Provisions a machine DID under your controller identity
  Auto-provisions MPC wallet with delegation scope

Delegation Scope:
  max_transaction_value  Configurable (default: 50 TNZO)
  max_daily_spend        Configurable (default: 200 TNZO)
  allowed_operations     Configurable
  time_bound             Configurable (default: 7 days)

The Per-Trade Cap is the Real Security Boundary

With max_transaction_value = 50 TNZO and a portfolio total of 200 TNZO, no single rebalance can exceed 25%drift in one shot. If you wanted to allow larger rebalances you'd either bump the cap or split the trade across multiple transactions — but neither happens without a controller signature, which is exactly the property you want.

Step 3: Spawn the Rebalancer Agent

Spawning creates the machine identity under your controller, attaches the delegation scope, and registers the agent on-chain. Pass the asset allocation and caps as flags:

tenzro agent spawn-template ref-yield-rebalancer-v1 \
  --param assets='[
    {"symbol": "TNZO", "target_bps": 4000},
    {"symbol": "USDC", "target_bps": 4000},
    {"symbol": "ETH",  "target_bps": 2000}
  ]' \
  --param max_transaction=50 \
  --param max_daily_spend=200 \
  --param drift_threshold=100 \
  --param scope_duration_days=7

The output confirms everything was provisioned:

Agent spawned successfully
========================

Agent ID:           rebalancer-a3f7c2
Agent DID:          did:tenzro:machine:<controller-did>:<uuid>
Controller DID:     did:tenzro:human:<your-uuid>
Wallet:             0x7a3b...c4e1

Delegation Scope:
  max_transaction_value:  50 TNZO
  max_daily_spend:        200 TNZO
  allowed_operations:     rebalance, trade
  time_bound:             7 days (expires 2026-04-15)

Target Allocation:
  TNZO:  40.00% (4000 bps)
  USDC:  40.00% (4000 bps)
  ETH:   20.00% (2000 bps)

Drift threshold: 100 bps

You can verify the identity was registered by resolving the DID:

tenzro identity resolve did:tenzro:machine:<controller-did>:<uuid>

Step 4: Dry-Run the Agent

Before committing real trades, run the agent in dry-run mode. This fetches current prices, computes drift against your targets, and shows what trades would be submitted — including delegation enforcement — without touching the chain:

tenzro agent run-template rebalancer-a3f7c2 --dry-run

The dry-run output walks through every asset:

Dry-run: ref-yield-rebalancer-v1 (rebalancer-a3f7c2)
=====================================================

Portfolio value: 200 TNZO

Asset Analysis:
  TNZO  current: 60.00% (6000 bps)  target: 40.00% (4000 bps)
        drift: -2000 bps  |  action: SELL 40 TNZO
        delegation check: PASS (40 < 50 max_transaction)

  USDC  current: 20.00% (2000 bps)  target: 40.00% (4000 bps)
        drift: +2000 bps  |  action: BUY 40 TNZO equivalent
        delegation check: PASS (40 < 50 max_transaction)

  ETH   current: 20.00% (2000 bps)  target: 20.00% (2000 bps)
        drift: 0 bps      |  action: NONE (on target)

Summary:
  trades to execute:  2
  total trade value:  80 TNZO
  daily spend check:  PASS (80 < 200 max_daily_spend)

Oversized trade test:
  simulated 250 TNZO trade -> BLOCKED by delegation
  (exceeds max_transaction_value of 50 TNZO)

No transactions submitted (dry-run mode).

The dry-run confirms three things: drift is computed correctly, each individual trade passes delegation enforcement, and an oversized trade would be blocked. This is the same enforce_operation check that runs during live execution.

Step 5: Live Execution

When the dry-run looks correct, execute for real. Drop the --dry-run flag:

tenzro agent run-template rebalancer-a3f7c2

The agent now submits real EVM transactions:

Live run: ref-yield-rebalancer-v1 (rebalancer-a3f7c2)
=====================================================

=== Computing drift ===
  TNZO  drift: -2000 bps  ->  SELL

=== Enforcing delegation scope ===
  trade value: 40 TNZO  ->  delegation OK

=== Dispatching EVM transaction ===
  tx hash:   0x3a7f...b2c1
  gas used:  23,412
  status:    success
  on-chain target weight for TNZO = 4000 bps

---

=== Computing drift ===
  USDC  drift: +2000 bps  ->  BUY

=== Enforcing delegation scope ===
  trade value: 40 TNZO  ->  delegation OK

=== Dispatching EVM transaction ===
  tx hash:   0x8e2d...f4a9
  gas used:  23,412
  status:    success
  on-chain target weight for USDC = 4000 bps

---

  ETH   drift: 0 bps  ->  already on target (skipped)

=== Run complete ===
  trades executed:    2
  total traded:       80 TNZO
  trader nonce:       2

Step 6: Review Results

After the run, verify the trades landed on-chain. You can check individual transactions by hash or query your wallet's updated balance:

# Check a specific transaction
curl -X POST https://rpc.tenzro.network \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tenzro_getTransaction",
    "params": ["0x3a7f...b2c1"],
    "id": 1
  }'

# Check the agent's wallet balance
tenzro wallet balance

# Verify the agent's identity and delegation scope are still active
tenzro identity resolve <agent-did>

You can also query the on-chain state directly to confirm the new target weights were written to the oracle contracts:

# Query block for the trade transactions
curl -X POST https://rpc.tenzro.network \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_getTransactionReceipt",
    "params": ["0x3a7f...b2c1"],
    "id": 1
  }'

What You Learned

You deployed a complete trading agent without writing any Rust code. The AgentKit template handled three Tenzro subsystems end-to-end:

The architecture is the important part: every trade is gated by a real cryptographic delegation scope before it touches the VM. The scope is the security boundary, not the agent code — which is exactly what you want when the agent is going to run unattended.

Customizing the Template

The ref-yield-rebalancer-v1 template supports additional parameters not covered in this tutorial: custom price oracle sources, multi-chain asset targeting, APY threshold evaluation, and automatic bridge + deposit flows. Run tenzro agent get-template ref-yield-rebalancer-v1 --verbose to see the full parameter reference.

Next Steps

  • Continue to the Yield Router tutorial to learn how to compose multi-protocol strategies
  • Read the DCA Agent tutorial for a time-based version of the same pattern
  • See the Multi-VM Commerce Workflows tutorial for the full set of EVM bytecode patterns