Agent
Decision Loop

Decision Loop — 5-Minute Keeper Cycle

The keeper runs every 5 minutes per vault — a fully autonomous decision cycle. The agent stands still more often than it acts.

Cycle Overview

┌─ Read live state ──────────────────────────────────────────────────────┐
│  Vault idle balance, deployed positions, venue reserve rate            │
└────────────────────────────┬───────────────────────────────────────────┘

┌─ Drift-band keeper ────────────────────────────────────────────────────┐
│  Is a rebalance due? (drift > 50bps from target weight)                │
│  If no → stand still, record nothing, wait 5 min                       │
└────────────────────────────┬───────────────────────────────────────────┘

┌─ Buy signals (pay.sh x402) ────────────────────────────────────────────┐
│  Load user's keypair from GCP Secret Manager                           │
│  Call enabled services (Vybe token-price) → pay $0.012 USDC            │
│  Attach receipt to decision record                                     │
└────────────────────────────┬───────────────────────────────────────────┘

┌─ Net-Edge gate ────────────────────────────────────────────────────────┐
│  gross_edge = venue_carry + signal_edge                                │
│  costs = gas + slippage + lockup + uncertainty + hurdle                │
│  net_edge = gross - costs                                              │
│  If net_edge ≤ 0 → DECLINE, record reason, wait 5 min                 │
└────────────────────────────┬───────────────────────────────────────────┘

┌─ Submit on-chain ──────────────────────────────────────────────────────┐
│  Clip amount to per-action cap                                         │
│  Build execute instruction (Merkle proof, nonce, expiry)               │
│  Sign with executor key → venue CPI/call                               │
│  Record: tx, netEdge, signalReceipt, marketplaceCalls                  │
└────────────────────────────┬───────────────────────────────────────────┘

┌─ VDL (Verifiable Debate Ledger) ───────────────────────────────────────┐
│  Hash-chain the decision (acted or declined)                           │
│  plan_hash = sha256(canonical(plan))                                   │
│  Link to previous → tamper-evident chain                               │
└────────────────────────────────────────────────────────────────────────┘

Key Discipline

The agent stands still more often than it acts. A decision to NOT allocate is recorded and auditable — the absence of action is as verifiable as the action itself.

Stage Details

1. Read Live State

The keeper reads directly from on-chain:

  • Vault idle balance (undeployed capital)
  • Active positions (allocated amounts, cToken balances)
  • Venue reserve rate (current supply APY from the lending protocol)

2. Drift-Band Check

Before paying for signals, the keeper checks whether a rebalance is even needed:

  • Is current allocation > 50bps from target weight?
  • If within band → sleep, no cost incurred
  • This prevents burning signal fees on cycles where no action is possible

3. Signal Acquisition (pay.sh)

If a rebalance might be needed, the agent purchases market data:

  • Loads the user's pay.sh keypair from GCP Secret Manager
  • Calls Vybe Analytics endpoint (token price, holders, DEX trades)
  • Pays ~$0.012 USDC per call via x402 protocol
  • Receipt (tx signature, amount, payee) attached to decision record

4. Net-Edge Gate

The core risk control — see Net-Edge Gate for full details:

  • Computes gross edge from venue carry + signal data
  • Subtracts ALL costs: gas, slippage, lockup cost, uncertainty, hurdle
  • Only proceeds if net edge > 0

5. On-Chain Submission

If approved by Net-Edge:

  • Clips the allocation amount to per-action cap
  • Builds the instruction with Merkle proof, nonce, and expiry
  • Signs with the executor key
  • Submits: Solend CPI (Solana) or venue.deposit() (EVM)

6. VDL Recording

Every decision — acted or declined — is recorded in the Verifiable Debate Ledger.

Running the Keeper

# Dry run (evaluates but doesn't submit)
cd app/backend
HERON_NETWORK=solana uv run python keeper_run.py
 
# Real execution (submits on-chain)
cd app/backend
HERON_NETWORK=solana uv run python keeper_run.py --execute
 
# The backend also starts the keeper scheduler automatically:
HERON_NETWORK=solana uv run uvicorn main:app --port 8787

Timing

ParameterValue
Cycle interval5 minutes
Drift threshold50 bps
Signal cost~$0.012 USDC per call
Max signal budgetConfigurable (PAYSH_BUDGET_USDC)