Robyn AnyGas

Integration cookbook

Copy-paste recipes to wire Robyn AnyGas into an agent or app. Every client defaults to the live gateway with zero config — no key required for reads. Base URL: https://api.anygas.xyz/svc.

Keyless reads Zero-config clients Sandbox = zero funds 0.25% routing fee
Honesty note. The MCP server, SDKs and adapters are MIT-licensed; the hosted relayer, routing service and contracts are proprietary — build on Robyn, don't clone it. Use sandbox mode (x-anygas-sandbox: 1) to test the full execute → status → DONE flow with no funds and no funded relayer.

⚡ The short version — one call

If you only read one section, read this. POST /api/agent/do takes a plain-language or structured intent, resolves the chains and amounts, quotes every rail, and hands back the exact payload to sign. No key, no SDK, one round trip.

curl  ·  intent in, signable payload out
curl -s https://api.anygas.xyz/svc/api/agent/do \
  -H 'content-type: application/json' \
  -d '{"intent":"send 25 USDC to 0xRecipient... on arbitrum","fromChain":8453}'

# -> { "status":"sign",
#      "rail":"robyn-floatlane", "receives":"24990000", "durationSec":15,
#      "signRequest":{ "chainId":8453, "spender":"0x1253...", "permit2Contract":"0x0000...78BA3",
#                      "tokenAddress":"0x8335...2913", "amount":"25000000",
#                      "submitTo":"POST /api/route/execute", "submitBody":{...} } }

Sign signRequest, POST submitBody to submitTo, done. Add -H 'x-anygas-sandbox: 1' to run the identical path end to end with no funds.

the three things that make an integration survive production
# 1. Retry safety - a timeout retry must never move funds twice
curl ... /api/route/execute -H 'x-idempotency-key: my-unique-id'
#    Same key replays the original result. Honoured identically in sandbox.

# 2. Typed errors - branch on errorCode, never on the message text
curl -s https://api.anygas.xyz/svc/api/errors
#    Every failure carries errorCode, retryable, retryAfterMs, suggestedAction.

# 3. Stop polling - stream the route instead
curl -N "https://api.anygas.xyz/svc/api/route/stream?id=<routeId>"
#    event: status on every change, event: done on terminal, then it closes.
browser  ·  zero install, no bundler
import { RobynAgent } from 'https://anygas.xyz/svc/robyn-agent-kit.js';

// works straight from a page: the gateway allows x-anygas-sandbox, x-idempotency-key,
// x-anygas-key and x-payment through CORS, and exposes the rate-limit headers back to JS.
const ag = new RobynAgent({ signer, svc: 'https://anygas.xyz/svc' });

const plan = await ag.agentDo({
  intent: 'send 25 USDC to 0xRecipient... on arbitrum',
  fromChain: 8453,
  sandbox: true            // prove it with no funds first
});
console.log(plan.status, plan.rail);   // "done" robyn-floatlane
Browser or Node, same call. agentDo() is in anygas-agent-kit 1.2.0 (npm and JSR @anygas/agent-kit) and in the zero-install browser build above. TypeScript types ship with the package — AgentDoParams, AgentDoSignRequest, AgentDoResult.
Free key, higher ceiling. The API is keyless by design. POST /api/keys/create gives you a free key that scopes rate limits to you instead of your shared IP and multiplies the ceiling — see GET /api/keys/quota. Full machine-readable surface: openapi.json.

1 MCP client config

Add Robyn to any MCP client — Claude Desktop, Cursor, or any agent runtime. Run it locally with npx, or point at the hosted streamable-HTTP endpoint (no install, no key). The hosted server is transactional: it hands you the exact payload to sign and relays it once you have signed — your key never leaves your wallet.

mcp.json  ·  local (npx)
{
  "mcpServers": {
    "robyn": { "command": "npx", "args": ["anygas-mcp"] }
  }
}
hosted · zero install (read-only)
# Streamable HTTP MCP endpoint — public, read-only, no key:
https://api.anygas.xyz/mcp

# also on JSR:  npx jsr add @anygas/mcp
# 14 tools. The ones that matter first:
#   robyn_prepare    - intent in, exact payload to sign out
#   robyn_submit     - relay your signed intent; the relayer pays the gas
#   robyn_sandbox_do - identical path, zero funds, nothing broadcast
#   robyn_errors     - the full error contract, so you can branch on errorCode

Reads (robyn_mesh, robyn_quote, robyn_route_status, robyn_errors) need no signer. robyn_prepare returns what to sign; you sign it with your own wallet and robyn_submit relays it, with the relayer fronting all gas. Prove the whole flow first with robyn_sandbox_do — no funds, no broadcast.

2 Raw HTTP — quote, sandbox, compare

No SDK, no key. All paths sit under /svc. Amounts are strings in the token's smallest units (USDC 6dp → "5000000" = 5 USDC).

curl · quote the best gasless route
curl -s https://api.anygas.xyz/svc/api/route/quote \
  -G --data-urlencode "fromChain=42161" \
     --data-urlencode "toChain=8453" \
     --data-urlencode "token=USDC" \
     --data-urlencode "amount=5000000"
# -> { gasless:true, bestOf:N, compared:[...], robynRouteFeeBps:25, durationSec:… }
curl · sandbox execute (zero funds, x-anygas-sandbox: 1)
curl -s https://api.anygas.xyz/svc/api/route/execute \
  -H 'content-type: application/json' \
  -H 'x-anygas-sandbox: 1' \
  -d '{"fromChain":42161,"toChain":8453,"fromToken":"USDC",
       "toToken":"USDC","amount":"5000000",
       "toAddress":"0xYourRecipient…"}'
# -> { status:"BRIDGING", sandbox:true, id:"sbx_…", robynRouteFeeBps:25 }
# poll: GET /svc/api/route/status?id=sbx_…  → RECEIVING → SWAPPING → SENDING → COMPLETED (~40s)
curl · compare rails for a cross-chain move
curl -s https://api.anygas.xyz/svc/api/route/compare \
  -G --data-urlencode "fromChain=42161" \
     --data-urlencode "toChain=solana" \
     --data-urlencode "fromToken=USDC" \
     --data-urlencode "toToken=USDC" \
     --data-urlencode "amount=50000000"
# non-EVM nodes are literal strings: "solana" · "stellar" · "bitcoin"

The API is keyless. Passing x-anygas-key: <key> only tags requests for usage visibility — it is never required. Over the per-IP limit → 429 {"error":"rate limited"}.

3 JavaScript / TypeScript

The Agent Kit wraps the whole API and defaults to the live gateway. Read methods need no signer; pass one only to execute.

install
npm i anygas-agent-kit   # MIT · also on JSR as @anygas/agent-kit
agent.ts
import { RobynAgent } from 'anygas-agent-kit';

// zero-config → defaults to https://anygas.xyz/svc
const robyn = new RobynAgent();

// gasless cross-chain quote — no signer needed for reads
const quote = await robyn.route({
  fromChain: 42161, toChain: 8453,
  fromToken: 'USDC', toToken: 'USDC', amount: '5000000'
});

// to execute, construct with a signer:
// const robyn = new RobynAgent({ signer });
// await robyn.crossChain({ fromChain: 42161, toChain: 8453, token: 'USDC', amount: '5000000' });

🛡 Preflight — never pay gas to discover a failure

One free, read-only call that answers the questions which otherwise cost gas: would a fixed corridor fee swallow the whole amount, is the recipient valid for that chain family, can this corridor actually settle, and is this size above the instant lane so a dearer bridge would quietly serve it. Every blocker carries a machine code and a fix, so branch on the code — never parse the prose.

preflight.ts
const pf = await agent.preflight({
  fromChain: 42161, toChain: 8453,
  fromToken: 'USDC', amount: '5000000',
  fromAddress: myAddress,     // decides your fee tier — members pay ZERO on micro-transfers
  toAddress: recipient,       // checked against the DESTINATION chain's address family
});

if (pf.decision === 'NO_GO') {
  for (const b of pf.blockers) console.error(b.code, '—', b.fix);
  return;                     // executing now would fail or deliver nothing
}

// Warnings do NOT block — they are things worth knowing before you commit:
//   ABOVE_LANE_CAPACITY  a bridge will serve this; the message names the exact split size
//   HIGH_COST            >=20% of the amount is withheld by vendor fees
//   NOT_A_MEMBER         a recognised NFT would make this transfer free
pf.warnings.forEach(w => console.warn(w.code, w.what));

pf.expected.rail;            // which rail will serve it
pf.expected.deliveredUnits;  // what ACTUALLY arrives, net of every fee

// Only now spend anything.
await agent.crossChain({ /* … */ });

Python: client.preflight(42161, 8453, "5000000", from_address=my_addr) — identical contract. Blocker codes are published in the error catalogue at GET /svc/api/errors, so you can generate handlers from it rather than hard-coding strings.

💰 Free & near-free micro-transfers (the float lane)

Small cross-chain transfers normally pay fees out of all proportion to the amount. On our own float lane there is no bridge in the path — we pay you from our inventory on the destination chain and take repayment on the source, one transfer, about one block. Transfers of $0.10–$25 to a low-cost chain are free if the sender holds a recognised member NFT, and cost a fraction of a cent otherwise. Always pass fromAddress: it is how membership is recognised, and without it you will be quoted the non-member rate.

micro-transfer.ts
// 1) QUOTE — fromAddress decides your tier, so always send it
const q = await fetch('https://anygas.xyz/svc/api/route/quote', {
  method: 'POST', headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    fromChain: 42161, toChain: 8453,        // Arbitrum -> Base
    fromToken: 'USDC', toToken: 'USDC',
    amount: '5000000',                          // $5, base units (6dp)
    fromAddress: myAddress,                       // <-- membership check
  }),
}).then(r => r.json());

const lane = q.floatlane;                        // absent = lane cannot serve this pair right now
if (lane) {
  lane.fee;                // "0" for members; a few thousandths of a cent otherwise
  lane.pricing.mode;       // free-micro-vip | micro-standard | rebalancing-discount | base
  lane.vip.member;         // true if fromAddress holds a recognised NFT
  lane.capNow;             // largest transfer this lane can serve RIGHT NOW (25% of dest float)
  lane.freeTier.failed;    // if not free, exactly which check failed
}

// 2) CHECK CAPACITY before promising a user anything — the lane is finite inventory,
//    not an unlimited bridge. Above capNow, quote falls back to an aggregator rail.
if (lane && BigInt(amount) > BigInt(lane.capNow)) {
  // split the transfer, or accept the (still cheap) bridged route in q.bridge
}

// 3) EXECUTE — one Permit2 signature; the relayer fronts gas on both sides
//    POST /api/route/execute with rail:'floatlane' and your signed permit2 object.
//    Add header  x-anygas-sandbox: 1  to rehearse the whole flow with ZERO funds first.

Am I a member? GET /svc/api/membership/status?address=0x… returns your tier and a plain-language benefits block. Recognised collections are listed live at /svc/api/floatlane/info under vip.registry. Every settled transfer, with its on-chain payout hash, is public at /receipts.

⚡ AnyGas Account — spend from yield

Keep your USDC in your own wallet in the best-yielding audited money market (Aave v3 or Moonwell, ~3–4%, auto-selected) — earning interest while it pays your gas. Grant the relayer a capped, revocable aUSDC allowance once, then spend from your yield with one signature — as any token or native gas on any chain, gaslessly. Non-custodial: we never hold your key, and there is no pool to hack.

yield-account.ts
import { RobynAgent } from 'anygas-agent-kit';
const robyn = new RobynAgent({ signer });   // your own wallet signer

// 1) your yield-aware position (aUSDC/mUSDC per chain + live APY, best of Aave v3 + Moonwell)
const acct = await robyn.yieldAccount();

// 2) one-time: cap your risk — approve the relayer for your aUSDC/mUSDC
await robyn.approveYield({ chainId: 8453, budget: 100_000000n });

// 3) spend from yield — ONE EIP-712 signature; delivered gaslessly, remainder keeps earning
await robyn.yieldSpend({
  srcChain: 8453, amount: 5_000000n,
  toChain: 42161, toAddress   // deliver 5 USDC to Arbitrum
});
Or over MCP. The hosted server exposes robyn_yield_account, robyn_yield_quote and robyn_yield_spend. Run npx anygas-mcp locally with ROBYN_SIGNER_KEY to execute. First-time setup: supply USDC to Aave v3 or Moonwell in your wallet, then approve the relayer for your aUSDC/mUSDC up to your risk budget.

🔑 EIP-7702 — someone else pays your gas

Post-Pectra, a plain EOA can delegate its code to a contract with a signed authorization, and anyone may submit that as a type-4 transaction. Robyn submits it and pays the gas — your account needs zero native token, and there is no bundler and no paymaster deposit anywhere in the path. Pay per sponsorship in USDC over x402, or preview the whole thing for free.

sponsored-7702.ts
import { Wallet } from 'ethers';
const account = new Wallet(PRIVATE_KEY);
const BASE = 'https://api.anygas.xyz/svc';

// 1) sign a 7702 authorization delegating to the Robyn batch executor
const d = await (await fetch(BASE + '/api/7702/delegate')).json();
const auth = await account.authorize({ address: d.deployments['8453'], nonce: 0, chainId: 8453 });
const authorization = { chainId: 8453, address: auth.address, nonce: 0,
  yParity: auth.signature.yParity, r: auth.signature.r, s: auth.signature.s };

// 2) verify it recovers you (free, no funds, nothing broadcast)
await fetch(BASE + '/api/7702/check', { method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ chainId: 8453, authorization }) });

// 3) price it for free — returns estGas, priceUsd and the exact envelope
const plan = await (await fetch(BASE + '/api/7702/sponsor', { method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ chainId: 8453, authorization, dry: true }) })).json();

// 4) sponsor for real: the same call WITHOUT dry, plus an X-PAYMENT header (x402, USDC on Base).
//    No header? You get HTTP 402 + accepts[] stating exactly what to pay.
What you get. The response carries the broadcast hash plus the settled x402 payment. The Robyn delegate is a minimal batch executor: execute(calls) when the account itself sends, or executeSigned(calls, nonce, deadline, v, r, s) when a relayer submits for you — so one signature can approve, swap and transfer in a single sponsored transaction. Delegation is revocable at any time by signing a new authorization.

4 Python

Same zero-config default. Great for backends, notebooks, and data pipelines.

install
pip install anygas
agent.py
from anygas import Robyn

robyn = Robyn()                       # zero-config → this gateway
mesh  = robyn.chains()                 # the live route graph

quote = robyn.route(
    fromChain=42161, toChain="solana",
    fromToken="USDC", toToken="USDC", amount="50000000")
print(quote)

5 Framework adapters

Robyn ships MIT adapters on npm as anygas-adapters for the Vercel AI SDK, LangChain and Coinbase AgentKit. For any runtime that speaks MCP — including CrewAI — the fastest, always-current path is to attach the hosted MCP server directly.

Vercel AI SDK — anygas-adapters
import { robynTools } from 'anygas-adapters/ai-sdk';
import { generateText } from 'ai';

await generateText({
  model, tools: robynTools(),   // quote/route/compare as AI-SDK tools
  prompt: 'Move 5 USDC from Arbitrum to Base gaslessly'
});
LangChain — anygas-adapters
# JS: import { robynLangchainTools } from 'anygas-adapters/langchain'
from anygas import Robyn
robyn = Robyn()
# expose robyn.chains / robyn.route as LangChain Tools
# in your agent's tool list.
Coinbase AgentKit — anygas-adapters
import { robynActionProvider } from 'anygas-adapters/agentkit';

// register alongside your other
// AgentKit action providers
const providers = [ robynActionProvider() ];
CrewAI / any MCP runtime — attach the server
# CrewAI supports MCP servers — point it at Robyn,
# no bespoke adapter needed:
{
  "mcpServers": {
    "robyn": { "command": "npx", "args": ["anygas-mcp"] }
  }
}
# or hosted HTTP: https://api.anygas.xyz/mcp
Prefer the MCP route when in doubt. Adapter package surfaces evolve; the MCP server (npx anygas-mcp or hosted https://api.anygas.xyz/mcp) exposes the same tools to every MCP-capable framework and is the most verifiable integration path. See the API docs for exact request/response shapes.
Robyn AnyGas · integration cookbook Full API docs → Playground → Status → Terms Privacy anygas.xyz