Skip to main content
TradeAgent is the on-chain identity for an AI trader. Holds name, Walrus strategy blob ref, agent address, human owner, BalanceManager id, TradeCap id, PredictManager id. Tracks reputation via signed PnL and a PLP score.

Custody surface

TradeAgent

public struct TradeAgent has key, store {
    id: UID,
    name: String,
    strategy_blob: vector<u8>,             // Walrus blob id
    agent_address: address,                 // operator address
    owner: address,                         // human owner
    balance_manager_id: ID,                 // DeepBook V3 BalanceManager
    trade_cap_id: ID,                       // DeepBook V3 TradeCap
    predict_manager_id: ID,                 // optional; 0 sentinel if absent
    is_active: bool,                        // pause / resume gate
    realized_pnl_abs: u128,                 // signed via two fields
    realized_pnl_sign: bool,
    plp_score: u128,                        // cumulative utilization share
}
Signed-PnL trick. Sui Move has no native i128. We split the signed quantity into realized_pnl_abs: u128 + realized_pnl_sign: bool. On record_outcome, the runtime computes new = old + delta in i128 mentally and writes back the abs+sign.

AgentOwnerCap

public struct AgentOwnerCap has key, store {
    id: UID,
    agent_id: ID,
}
Gates the three owner-only actions:
public fun pause(agent: &mut TradeAgent, cap: &AgentOwnerCap)
public fun resume(agent: &mut TradeAgent, cap: &AgentOwnerCap)
public fun record_outcome(
    agent: &mut TradeAgent,
    cap: &AgentOwnerCap,
    pnl_delta_abs: u128,
    pnl_delta_sign: bool,
    plp_score_delta: u128,
)
All three abort with ENotOwner if cap.agent_id != object::id(agent).

Registration

public fun register_agent(
    registry: &mut AgentRegistry,
    name: String,
    strategy_blob: vector<u8>,
    agent_address: address,
    balance_manager_id: ID,
    trade_cap_id: ID,
    predict_manager_id: ID,
    ctx: &mut TxContext,
): (TradeAgent, AgentOwnerCap)
Wraps AgentRegistered { agent_id, name, owner, agent_address } event. Wired via scripts/register-trade-agent.ts and the /agents Create wizard.

Pause/resume + indexer

pause and resume emit no events (verified at agent.move:215). The server paused column in the agents table is stuck at the registration default. Authoritative source for an agent’s active state is sui.getObject(TradeAgent).is_active. Frontend OwnerControls and the agent-service tick guard both read it live. Do not trust the API field.

Tests

No dedicated test file in tests/; covered indirectly by predict_facade_tests and the per-agent flows.