← All posts

How to let an AI agent swap tokens: safely, and MEV-protected

Agents can already pay. Swapping is the harder, riskier half. Here is how to give an AI agent the ability to swap tokens through Ophis (via an MCP server, the Intent API, or the SDK), with the safety rails (bounded orders, a pinned receiver, MEV-protected settlement) that stop an autonomous signer from draining itself.

  • ai-agents
  • mcp
  • mev
  • defi
  • swaps
Ophis: intent-based DEX aggregator for the agent era

2026 is the year AI agents got wallets. Giving an agent the ability to pay is largely a solved problem now: stablecoin rails, x402, and a handful of provider SDKs cover it. Giving an agent the ability to swap, to turn one token into another at a fair price without getting picked off, is the harder half. It is also where naive integrations quietly lose money.

This is a walkthrough of wiring swaps into an agent through Ophis, and, more importantly, the safety model that keeps an autonomous signer from turning into an autonomous victim.

Paying is easy. Swapping is where it goes wrong.

A payment is a one-sided transfer. A swap is an adversarial action on a public mempool. The instant an agent broadcasts a market swap, searchers can sandwich it: buy in front, sell behind, and pocket the spread. A human does this occasionally; an agent that rebalances or DCAs on a schedule is a predictable, high-frequency, fully-automated target. The MEV tax compounds on every trade.

And an autonomous signer has no wallet pop-up to catch a bad order. The three things a human would notice in a confirmation dialog all fail silently for a machine:

  • a receiver set to an address that is not the owner: the bought tokens land somewhere else, and the signature makes it irreversible;
  • an unbounded price: the order fills far below the quote the agent reasoned about;
  • a wrong settlement contract or orderbook host: the order routes around your solver and collects nothing.

Ophis is built for exactly this. It is intent-based: you do not broadcast a swap, you sign a bounded order and a competitive solver network races to fill it. It is MEV-protected: orders settle in batch auctions at a uniform clearing price, so there is no in-batch ordering to exploit, no sandwiching. And the agent signs a bounded capability, not an arbitrary transaction.

The fastest path: point your agent at the MCP server

If your agent speaks the Model Context Protocol, you do not have to write any swap code. Ophis runs a hosted, streamable-HTTP MCP server:

https://mcp.ophis.fi/mcp

It exposes six tools:

ToolWhat it does
parse_intentParse a natural-language request into a structured intent.
get_quoteFetch an executable quote for a parsed intent.
build_orderBuild a bounded, ready-to-sign order (receiver pinned to the owner by default).
submit_orderSubmit a signed order to the correct per-chain orderbook.
lookup_tierLook up a wallet’s 30-day volume tier and rebate status.
list_chainsResolve supported chains and their settlement / orderbook hosts.

Point any MCP client (Claude, Cursor, or your own agent loop) at the URL:

{
  "mcpServers": {
    "ophis": {
      "type": "http",
      "url": "https://mcp.ophis.fi/mcp"
    }
  }
}

The important property: Ophis never holds keys. build_order hands back a bounded order with the receiver pinned to the owner; the agent signs it locally; submit_order relays the signature. The signature is the trust boundary: the agent commits to a specific, bounded order, nothing more.

Not on MCP? Wrap the Intent API as a tool

Any function-calling agent (LangChain, an OpenAI Assistant, AutoGPT, a custom tool loop) can call the Intent API directly. It takes free-form text and returns structured entities you map to a swap link the user signs.

from langchain_core.tools import tool
import requests

# The chains the Intent API can return, mapped to their chain IDs (see the docs).
CHAIN_IDS = {
    "ethereum": 1, "optimism": 10, "bnb": 56, "gnosis": 100, "polygon": 137,
    "base": 8453, "ink": 57073, "linea": 59144, "arbitrum": 42161,
    "avalanche": 43114, "plasma": 9745,
}

@tool
def ophis_swap_intent(text: str) -> dict:
    """Parse a natural-language swap request into a structured Ophis intent and a
    deep link the user can open to review and sign. Use whenever a user wants to
    swap, buy, or sell a token. Always show the link to the user, never
    auto-execute a trade."""
    r = requests.post("https://ophis.fi/api/intent", json={"text": text}, timeout=10)
    r.raise_for_status()
    parsed = r.json()["data"]
    by_type = {e["type"]: e["value"] for e in parsed["entities"]}
    chain = by_type.get("chain")
    if chain and chain not in CHAIN_IDS:
        raise ValueError(f"unmapped chain {chain!r}; never silently misroute")
    chain_id = CHAIN_IDS.get(chain, 1)  # no chain named: default to Ethereum
    sell, buy = by_type.get("sellToken", "_"), by_type.get("buyToken", "_")
    return {"intent": parsed, "deeplink": f"https://ophis.fi/#/{chain_id}/swap/{sell}/{buy}"}

The tool returns both the structured intent (so the agent can reason about the trade) and a link (so the human can sign it). The full chain map and an AutoGPT / OpenAI function schema are in the AI agent docs.

Building and signing an order yourself

If you want to place orders programmatically, you build and sign a CoW Protocol order. Four things must each be exactly right, and every one of them fails silently (a rejected order, a wrong-chain trade, or zero fee collected) if you guess. The @ophis/sdk exists so you do not have to:

import {
  getOphisOrderbookUrl,
  getOphisOrderDomain,
  buildOphisAppDataPartnerFee,
  assertReceiverIsOwner,
} from '@ophis/sdk'

// 1. Resolve the orderbook host from the chain ID. Optimism is self-hosted at
//    optimism-mainnet.ophis.fi, NOT api.cow.fi, and the SDK gets this right.
const orderbookUrl = getOphisOrderbookUrl(chainId)

// 2. Build the partner-fee appData (CIP-75 volume shape, the correct rate per
//    chain/pair). This is what attributes the swap (and the rebate) to you.
const partnerFee = buildOphisAppDataPartnerFee(chainId)

// 3. Pin the receiver to the owner BEFORE signing. In the UI a wallet prompt
//    gates this; an autonomous signer has no such gate, so guard it in code.
assertReceiverIsOwner(owner, order.receiver) // throws if receiver !== owner

// 4. Sign EIP-712 typed data against the per-chain domain. The Ophis-operated
//    chains do not use CoW's canonical settlement, so build the domain from the
//    chain ID, never the SDK default.
const signature = await wallet.signTypedData(getOphisOrderDomain(chainId), ORDER_TYPES, order)

The full four-step guide covers the appData hashing and the EIP-712 order struct in detail. The one-line summary: let the SDK resolve anything that is chain-specific.

Agents that trade earn: the rebate

Here is the part that flips swaps from a cost center to a revenue line. Every swap routed through your integration carries the Ophis partner fee: a flat 0.10% (just 0.01% for stablecoin-to-stablecoin pairs) written into the order’s appData. Integrators earn a rebate on the volume they route, and the lookup_tier tool surfaces a wallet’s 30-day volume tier.

An agent that swaps frequently is not an expense to its builder; it is recurring, attributable volume. The more your agent trades, the more you earn back.

Going fully autonomous (read this first)

Everything above keeps a human in the signing loop. The moment you remove that human and let the agent sign on its own, off-chain helpers stop being enough: a compromised or prompt-injected agent will sign whatever it is told. “The human always signs” is a documented social contract, not an enforced boundary. Before you go unattended, move the boundary into code:

  1. Funds in a smart account (Safe). The agent never holds the fund-owning key; it only proposes orders. An EIP-1271 validator or Safe module approves only order hashes that satisfy policy.
  2. A deterministic policy gate between the (untrusted) LLM and any signature: tokens from a chain-scoped allowlist only (never an LLM-emitted address); receiver pinned to the account; appData pinned to the Ophis canonical with hooks forced empty; a limit price within X% of an independent, staleness-checked oracle; per-trade and rolling-daily notional caps; a short validTo.
  3. Containment: a bounded vault-relayer allowance (the blast radius if policy fails once), a guardian key that can pause or revoke signing, keys in an HSM/TEE, and a tamper-evident audit trail.
  4. Defense in depth: enforce the policy in two places: the EIP-1271 validator/signer and server-side at orderbook ingestion.

The autonomous-trading section of the docs spells out the full kit. The rule of thumb: an autonomous integrator is one unpinned receiver away from draining itself, so do not ship one until the policy is in code, not prose.

Start here

Ophis is the swap layer for the agent era: MEV-protected, self-custody, and revenue-aligned with the people who integrate it.