Skip to main content
Delegated agents let an owner wallet approve a separate signer for trading automation. The owner keeps custody, withdrawals, collateral movement, and delegation management. The agent can only perform the trading actions allowed by its policy. Use delegated agents for market-making bots, execution agents, institutional trading systems, and AI agents that should place or manage orders without holding custody.

Surface Map

Model

  • The owner owns balances, positions, PnL, perps accounts, and withdrawals.
  • The agent signs and submits allowed trading actions.
  • Orders are recorded under the owner user ID, with the agent wallet captured as signer.
  • Policies can restrict actions, markets, margin accounts, order types, time-in-force, leverage, notional size, expiry, and the IP addresses the agent may create its session from. Concurrent open-order caps are unsupported.
  • An owner holds at most 10 active, unexpired agents. Registering another past that is rejected until one is revoked or expires.
  • Margin accounts can be resolved by Monaco from owner, market, and optional strategyKey.
Delegated agents do not receive the owner private key and do not trade from a separate delegated account. They create an owner-scoped delegated session, then Monaco records each request as owner account activity with the agent address preserved for policy enforcement and audit history.
Delegated sessions cannot withdraw or move owner collateral outside the actions allowed by the policy. Every order mutation re-checks the active delegation before it can affect the owner’s account.

Delegated Market-Maker Flow

1

Owner creates the delegation

The owner signs normally and creates or updates an agent policy with the external wallet allowed to act, the allowed markets, action types, order types, time-in-force values, leverage limits, notional caps, optional margin account scope, optional IP allowlist, and expiry (14 days from now by default, at most 180 days ahead).Only the owner or master account should be able to grant this permission. The market maker never receives the owner private key.
2

Agent authenticates as itself

The market maker logs in with its own wallet and Monaco session. It is not given a separate delegated account and it does not impersonate the owner at wallet-auth time.
3

Agent discovers delegated owners

The agent calls listDelegatedOwners to find active owners that delegated to the authenticated agent wallet. The lookup is keyed by the agent wallet address and returns the ownerUserId needed to open a delegated session.
4

Agent adopts the owner-scoped session

The agent calls loginAsDelegatedOwner(ownerUserId). The SDK generates a fresh Ed25519 session keypair locally and sends only the session public key to Monaco with the selected ownerUserId.If the owner has an active, non-expired delegation to that agent wallet, and the agent calls from an address inside the delegation’s IP allowlist when it has one, Monaco creates a delegated auth session that acts on the owner user ID while preserving the agent address as the actor, and the SDK installs it as the active session so subsequent calls act on the owner.
5

Agent signs trading requests

With the owner session adopted, the agent signs create, cancel, replace, and close-position requests with the delegated session key. Downstream services see owner-scoped account state plus delegated-agent context.
6

Monaco re-checks policy on every mutation

Before create, cancel, replace, or close-position actions, Monaco reloads the active delegation for (ownerUserId, agentAddress). The request is rejected if the delegation is revoked, inactive, expired, missing, or outside policy limits.
7

Orders affect the owner account

If policy checks pass, the order mutates the owner’s allowed spot or perps account. Collateral, positions, PnL, risk, liquidation state, fees, and fills all belong to the owner. The agent address and delegation ID remain available for audit and attribution.
8

Expiry has two layers

A delegated session expires no later than its backing delegation. Every signed request, including reads and session refresh, requires an active, unexpired delegation. Shortening or revoking the grant also ends access for existing sessions. Connected WebSockets enforce this at their next periodic session revalidation (currently every 60 seconds). Existing orders are not automatically canceled.

Owner Setup

The owner creates or updates an agent policy.
agentAddress, allowedActions, and allowedTradingPairIds are required in the REST JSON body. Omitting either required array returns 400 Invalid JSON payload. The four optional arrays — allowedMarginAccountIds, allowedOrderTypes, allowedTimeInForce, and ipAllowlist — accept omission, null, or [] over REST. The TypeScript SDK accepts omission or [] for them. Omit expiresAt for the default of 14 days from now; a value more than 180 days ahead returns 400. Upsert replaces the whole policy, so an update without expiresAt also resets the expiry to 14 days from the update.
Omit maxOpenOrders. The server rejects any configured value because this limit was never enforced. Do not display it as an active protection in your UI.
Store agent.id for later revocation.

Agent Session

The agent authenticates with its own wallet, discovers owners that delegate to it, then adopts an owner-scoped delegated session with loginAsDelegatedOwner. Adopting the session installs a fresh owner-scoped session key as the SDK’s active auth state, so every subsequent read and order call acts on the owner account.
listDelegatedOwners is keyed on the agent’s authenticated wallet and returns only non-revoked, non-expired delegations. Use loginAsDelegatedOwner rather than calling createDelegatedSession directly: the latter registers a session but does not switch the SDK to it, so calls would keep signing with the agent’s own session and act on the agent account instead of the owner. Keep the agent’s ordinary login in a separate SDK instance or secure credential store: adopting a delegated session replaces the current instance’s auth state. refreshAuth() can extend a still-valid session only up to the grant’s expiry; it cannot renew the owner’s authorization or recover an expired session. After grant expiry, the owner must renew the grant. An expired session requires a fresh delegated session using the agent’s own wallet login. Grant expiry blocks access while the grant is expired; it does not permanently revoke session keys. After owner reauthorization, an existing unexpired session may become usable again, including a session issued before the grant was shortened. Successfully revoking the agent also marks its existing sessions revoked; renewing the grant does not revive those revoked sessions. Reconcile a failed revocation before reauthorizing the agent. The delegated session uses owner account state with delegated-agent context:

Trading With Auto-Resolved Perps Accounts

For normal delegated perp trading, omit marginAccountId. Monaco resolves or creates the owner-owned bucket for the market and optional strategy.
Use an explicit marginAccountId only for advanced reconciliation or fixed-bucket institutional flows.

Price-Bounded Immediate Execution

For a delegated grant with maxOrderNotional, use a LIMIT order with an explicit price and timeInForce: "IOC" when partial fills are acceptable. The grant must allow CREATE_ORDER, the market or margin account, LIMIT, and IOC. IOC fills immediately at the limit or better and cancels any unfilled remainder; it never leaves that remainder resting. Choose the limit from a fresh reference price and your execution tolerance, using decimal arithmetic:
  • BUY: maximum price = reference × (1 + toleranceBps / 10000), rounded down to the market’s tickSize.
  • SELL: minimum price = reference × (1 - toleranceBps / 10000), rounded up to tickSize.
  • Round quantity down to the market’s quantityStepSize within base-asset precision, then check minimum/maximum order size and limitPrice × quantity <= maxOrderNotional. Submit price and quantity as human-readable decimal strings, not raw token units. The cap is inclusive and uses the entire requested quantity, even if only part can fill.
For example, a BUY reference of 60000 with a 100 bps tolerance gives a 60600 limit. If the market permits 0.0001 base units and that price tick, its requested notional is 6.06 quote units:
Do not set postOnly: true with IOC or pass slippageToleranceBps on this limit order. The explicit price is its execution bound. A capped MARKET request without a price is rejected with Delegated agent maxOrderNotional requires a limit price; a market-order slippage tolerance does not supply that missing policy input. Inspect matchResult.status, totalFilled, and remainingQuantity. A partial IOC fill is terminal CANCELLED with a nonzero totalFilled; an IOC with no executable liquidity is REJECTED. A successful submission does not promise a full fill. Reconcile fills before submitting another order for any remaining intent. maxOrderNotional checks submitted price × quantity at admission. It is not an aggregate exposure, collateral, or fee budget. A SELL can execute above its minimum price, so its realized quote proceeds can exceed that product. Fees and margin-risk checks still apply, and a stale reference can result in a partial fill or no fill. For margin orders, simulate the risk bucket order against its current exposure before placement. A preview does not reserve collateral: balances, fees, exposure, and prices can change before the order arrives. Keep the reported margin amounts as decimals and do not round away a positive shortfall, even a very small one; admission still requires actual funding.

Close Position

Closing a perp position is treated like order creation because Monaco submits a close or reduce order. Delegated sessions must pass the same policy checks used for create-order actions before a close can be submitted. For batch close-all flows, delegated sessions should be scoped to an explicit tradingPairId. That prevents a broadly authenticated delegated session from closing every open position across all markets without a market-specific policy check.

Policy Design

Start narrow and widen only when the agent needs more capability: Each listed scope must match: an agent listing a margin account trades only that account, and only on its listed markets if it lists any. A market-only agent (no allowedMarginAccountIds) trades its listed markets in every margin account. Both scopes empty deny all orders; empty scopes do not grant access to every market or account. Active delegated sessions can read owner account data; trading scopes do not filter that data. The IP allowlist is checked when the agent creates its delegated session, against the address the request arrives from. A caller outside every listed range gets 403. Only session creation is checked: a session already created keeps working from any address until it expires or the grant is revoked, so revoke the grant to cut off a session after narrowing the allowlist. Entries are stored normalized to CIDR form, so a bare address reads back as /32 (IPv4) or /128 (IPv6).

Permission Summary

UI Rules

  • Show the owner which wallet is authorized and what it can do.
  • Make revocation obvious and immediate.
  • Display policy expiry and market restrictions near agent status.
  • Log agent signer address on order history views when relevant.
  • For bots and AI agents, prefer narrow market and notional limits by default.