Trion Documentation Options live · Perps in open beta
Browse documentation

Agent grants and limits

In one paragraph. An agent grant is an EIP-712-signed authorization from a trader's wallet that lets a separate agent key place orders on the trader's account inside explicit bounds — max order size, max position, reduce-only and expiry. The matcher enforces every bound on every order at admission and again at fill, so a grant is the exact, revocable scope of what an agent can do; it cannot grant anything else, and it can never grant withdrawal.

The grant

interface AgentGrant {
  trader: Address;          // account owner; signs the grant
  agent: Address;           // agent key that signs orders for `trader`
  marketId: Hex;            // one market per grant
  strategyId: Hex;          // non-zero, random per grant; every agent order carries it
  strategyEpoch: number;    // == OrdersV2.strategyEpoch(trader, strategyId) at grant time
  maxOrderQty: bigint;      // lots per order
  maxPositionLots: bigint;  // |position| the agent may open to; reduce-only is always allowed
  reduceOnly: boolean;      // true = the agent may only reduce/close
  expiry: bigint;           // unix seconds; now < expiry <= now + 180 days
  nonce: bigint;
}
FieldBound it sets
traderWhose account the agent acts on
agentThe key that signs the orders
marketIdOne market per grant — a grant never spans markets
strategyId / strategyEpochScoped revocation: every order carries them, and advancing the epoch kills everything under the grant
maxOrderQtyLargest order (in lots) the agent may submit
maxPositionLotsLargest absolute position the agent may open to; reduce-only orders are always allowed
reduceOnlyWhen true, the agent may only reduce or close, never open
expiryHard deadline; strictly before now + 180 days

EIP-712 domain

The grant is signed under

{ name: "TrionAgentGrant", version: "1", chainId: 4663, verifyingContract: <market OrdersV2> }

with primary type AgentGrant. Helper functions (agentGrantTypedData, hashAgentGrant, agentRevokeMessage, AGENT_GRANT_MAX_LIFETIME_SECONDS) are shared across the SDKs and the MCP server, so a grant signed in one place verifies in the others.

How each bound is enforced

The matcher checks grants inside its single-writer queue on every order admission and fill attempt:

Revocation and expiry — the five paths

Any one of these ends the grant's authority:

  1. Signed revoke. personal_sign("trion-revoke-agent:<chainId>:<SYMBOL>:<trader lowercase>:<agent lowercase>:<issuedAt>") by the trader or the agent (issuedAt within ±60 s). Every not-yet-revoked grant for the pair is marked revoked, queued admissions are drained, and every resting order under those strategyIds is cancelled.
  2. On-chain epoch advance. OrdersV2.advanceStrategyEpoch(strategyId, n) cascades and cancels everything under that strategy id.
  3. Expiry. Once expiry passes, the grant is dead and no order bound to it can fill.
  4. Replacement. Registering a new grant for the same (trader, agent) supersedes the old one and cancels the resting orders it admitted.
  5. Maker fill cancellation. A resting agent order is bound at admission to the grant that admitted it; it is cancelled instead of filled if the grant is no longer active, or if the fill would grow |position| past maxPositionLots.

Matcher API for agents

The agent routes live on the perp matcher API (https://api.trion.market/perp). They are gated only by the matcher's agent-grants switch (AGENTS_DISABLED, 404, when it is off); there is no invite list on this path. Since 2026-09-26 the OAuth connect page has no invite list either, so any wallet can register a grant. Both paths are in beta and trade the CMPT-USD perpetual, which is in open beta.

RoutePurpose
POST /v1/agents?symbol=Register a grant ({ grant, signature }). A newer grant for the same pair supersedes the old one and cancels its resting orders. Returns 201 { grantHash, status: "active", cancelled }.
GET /v1/agents?symbol=&trader=List the trader's grants with status (active / revoked / expired / superseded).
POST /v1/agents/revoke?symbol=Revoke ({ trader, agent, issuedAt, signature }). Returns { revoked, cancelled }.
POST /v1/orders?symbol=Place an order. With agent set, the signature must recover to the agent, the grant must be active, and the order must sit inside the bounds above.
DELETE /v1/orders/:hashCancel a resting order. The signer may be the trader, or an agent whose active grant's strategyId equals the order's.
POST /v1/orders/cancel-allAn agent signature cancels only its own grant's strategyId orders.

Grants persist in the matcher's store, so revocation survives a restart.

Errors

CodeMeaning
403 AGENT_NOT_AUTHORIZEDNo active grant, wrong signer, or wrong strategy
400 AGENT_LIMITA bound was exceeded; the message names the bound
400 INVALID_GRANTThe grant shape or signature is invalid
403 BAD_SIGNATURESignature verification failed
409 REVOKE_REPLAYA stale issuedAt on revoke
403 AGENT_POLICY_UNSUPPORTEDAn agent tried to submit a strategy policy (see below)

What agents cannot do

See Connect an AI assistant (MCP) for how the grant appears in the OAuth flow, and Signed orders for the order struct.

Source trail: docs/developers/agent-access.md §§2–3 (grant type, matcher routes, revocation), overdrive/exchange/matcher/src/agent-routes.ts, perp-routes.ts, overdrive/exchange/core/src/v2.ts (grant EIP-712 helpers), overdrive/perps/src/v2/OrdersV2.sol (epoch revocation), overdrive/exchange/sdk/src/agents.ts.

Repository-owned documentation · October 2026 · Educational material, not investment advice and not an audit.