The owner of a TradeAgent has four on-chain actions, all gated by AgentOwnerCap (Move-level) or by the server’s ownerAddress check (hosted-fleet endpoints). Surfaced as the OwnerControls block on /agents and /agents/:agentId.
Reclaim (hosted fleet)
The hosted fleet agent owns a PredictManager whose owner is the agent’s ephemeral key. The user can’t sign predict_manager::withdraw from their wallet directly. Instead:
Server decrypts the agent key, signs predict_manager::withdraw_all<DUSDC>, and transfers the resulting coin to the fixed ownerAddress from the agent_runtime row. The recipient is never user-supplied. the agent can only reclaim to its registered owner.
Frontend wiring:
Demo line: “your funds, your keys. The agent never had the right to keep them.”
Reclaim (CLI / single-agent path)
For a TradeAgent registered via pnpm agent:register, the owner withdraws from the BalanceManager directly. balance_manager::withdraw_all<DUSDC> is owner-gated by Move:
Renders only when account.address === agent.owner. Reads the BalanceManager id via sui.getObject(TradeAgent) (field balance_manager_id).
Fund (hosted fleet)
Owner signs a predict_manager::deposit<DUSDC> PTB from their wallet (sponsored), then the frontend POSTs /v1/agents/:id/sweep so the deposited coin lands inside the agent’s PredictManager via a server-signed sweep call. Two-step is required because Predict’s deposit asserts sender == manager.owner and the manager is owned by the agent’s ephemeral key.
POST /v1/agents/:id/sweep updates last_funded_ms so the auto-disable rule (3-day idle + < $1 PM balance) doesn’t fire.
Pause / Resume
Both abort with ENotOwner if cap.agent_id != object::id(agent).
Neither emits an event. The server paused column in the agents table is stale. The frontend OwnerControls and the fleet runtime’s tick guard both read is_active live via sui.getObject(TradeAgent). Do not rely on the API field.
Frontend wiring:
Header on /agents/:agentId always surfaces an ACTIVE (green) or PAUSED on-chain (warn) pill so the state is never ambiguous.
Runtime gate
Both the legacy single-agent runtime and the hosted fleet read is_active at the start of every tick:
Defensive default = active so transient RPC hiccups don’t silently halt the agent.
Three kinds of “off”
- Pause on-chain. Owner signs
agent::pause. Runtime keeps polling but never trades. Reversible.
- Reclaim DUSDC. Owner POSTs
/v1/agents/:id/reclaim (hosted) or signs balance_manager::withdraw_all (CLI). Funds back in wallet.
- Auto-disable. Server flips
enabled=false if PM balance < $1 for > 3 days. Fleet stops ticking. Owner can reclaim, then either fund + reactivate or leave it dead.