Aionmarket Trading
v1.0.2Core trading skill for AION Market prediction market agents. Provides agent setup, wallet binding, market search, automated pre-trade checks, risk-aware trad...
Like a lobster shell, security has layers — review code before you run it.
Skill: aionmarket-trading
Core trading operations for AI agents on AION Market / Polymarket. This skill covers the foundational capabilities — agent lifecycle, wallet setup, market data, order execution, and position management.
Strategy skills (market discovery, signal generation, automated loops) are separate skills that build on top of this one.
Scope
- Applies to: Any AI agent that needs to trade prediction markets through AION Market
- Does NOT cover: Strategy logic, autonomous market scanning loops, or signal generation (see dedicated strategy skills)
Prerequisites — USER MUST PROVIDE
Before this skill can operate, the user must supply:
| Secret | Where to set | Example |
|---|---|---|
| Agent API Key | AIONMARKET_API_KEY env var or .env | sk_live_Ab12Cd34... |
| Wallet Private Key | WALLET_PRIVATE_KEY env var or .env | 0xabc123... (64 hex chars) |
That's it. The skill will:
- Derive the wallet address from the private key automatically
- Call Polymarket's CLOB auth endpoint to derive API Key / Secret / Passphrase using the private key signature
- Register the CLOB credentials with AION Market via
register_wallet_credentials() - Automatically check wallet readiness before trading: balance, gas, allowance, and market context
- Automatically approve allowance if needed and technically possible
If the private key is missing, STOP and ask the user to provide it. Never guess, fabricate, or skip credential setup. Store secrets in a local
.envfile (never commit to git) or export as env vars.
Assumptions
- Python 3.9+
aionmarket-sdk >= 0.1.2installed (pip install aionmarket-sdk)py-clob-clientfor order signing and credential derivation- Agent has been registered or will be registered as part of the flow
- Polymarket CLOB credentials are derived automatically from private key via
py-clob-client - All SDK methods return plain dicts/lists; errors raise
ApiError get_markets()returns events with nestedmarkets[]sub-markets — trading fields likeconditionId,clobTokenIds,outcomePriceslive on the sub-market, not the event
Principles
- Always check context before trading — call
get_market_context()before every order - Never trade without a thesis — every trade needs explicit reasoning
- Respect risk limits — honour
riskLimit,maxTradesPerDay,maxTradeAmount - Fail loudly — catch
ApiErrorand surface the message; never swallow errors - Self-custody — wallet keys belong to the user; SDK only stores encrypted CLOB credentials
- Automate mechanical steps — do not ask the user to manually confirm balance checks, gas checks, allowance checks, or approval after the private key is available
- Verify execution independently — if the wrapper response is weak, validate through Polymarket directly before reporting failure
Automation Defaults
Unless the user explicitly overrides them, the agent should use these defaults:
- default trade mode:
market - default buy size:
2USDC - default behavior: auto-select a valid market candidate from the requested strategy scope
- default pre-trade workflow: derive wallet, register wallet credentials, check balance, check gas, check allowance, auto-approve if needed, then trade
- default post-trade workflow: query recent Polymarket trades and orders if the SDK result is generic, null, or ambiguous
The agent should ask the user only for information it cannot safely infer or execute itself.
Constraints
MUST
- Set
AIONMARKET_API_KEYbefore any authenticated call - Register Polymarket CLOB credentials before live trading
- Check wallet balance, gas balance, and relevant allowance before submitting any order
- Call
get_market_context()before placing any trade - Handle
ApiErroron every SDK call - Save the API key returned by
register_agent()immediately — it is shown only once - Send a full signed order object and
walletAddresswith every trade - Verify downstream execution via Polymarket when SDK responses are incomplete
SHOULD
- Use environment variables for all secrets (never hardcode)
- Call
get_briefing()periodically (heartbeat pattern) for risk alerts and opportunities - Set conservative risk limits first via
update_settings(), then scale up - Cancel stale open orders promptly
- Rotate API keys every 90 days
- Prefer market orders for simple one-shot execution unless the user explicitly requests a limit order
- Auto-approve required spenders when allowance is missing and gas is sufficient
AVOID
- Trading without checking
warningsfrom market context - Exceeding the agent's configured
maxTradeAmount - Sharing or logging API keys, CLOB secrets, or private keys
- Calling
cancel_all_orders()without confirming with the user first - Making trades in markets the agent has not researched
- Treating a wrapper
INTERNAL_ERRORas final without checking whether Polymarket actually matched the order
Installation
pip install aionmarket-sdk py-clob-client python-dotenv
py-clob-client— Polymarket official SDK, derives CLOB API credentials from private keypython-dotenv— loads.envfile automatically
Environment Setup
Create a .env file in your project root (add .env to .gitignore):
# .env
AIONMARKET_API_KEY=sk_live_...
WALLET_PRIVATE_KEY=0xabc123...your_64_hex_char_private_key
# Optional — only set this when AION Market docs tell you to use
# a non-production environment URL for your target environment.
# Do not hardcode a staging URL copied from an old example.
# AIONMARKET_BASE_URL=https://<documented-aionmarket-base-url>/bvapi
Or export directly:
export AIONMARKET_API_KEY="sk_live_..."
export WALLET_PRIVATE_KEY="0xabc123..."
Derive Wallet Address and CLOB Credentials from Private Key
import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
load_dotenv() # loads .env file
private_key = os.environ["WALLET_PRIVATE_KEY"]
# Use Polymarket CLOB client to derive credentials from private key
polymarket = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
)
creds = polymarket.create_or_derive_api_creds()
# creds contains: api_key, api_secret, api_passphrase
wallet_address = polymarket.get_address()
print(f"Wallet address: {wallet_address}")
print(f"CLOB credentials derived successfully")
Base URL resolution priority:
- Explicit
base_urlargument in code AIONMARKET_BASE_URLenvironment variable- Production default:
https://api.aionmarket.com/bvapi
Use the SDK's documented resolution order above. Do not hardcode a sandbox or staging URL in sample code unless that exact environment URL is the current one documented by AION Market.
Workflow: Agent Bootstrap
Run once to create an agent and bind a wallet.
Step 1 — Register Agent
from aionmarket_sdk import AionMarketClient
client = AionMarketClient() # no key needed for registration
registration = client.register_agent("my-trading-bot")
api_key = registration["apiKeyCode"]
claim_code = registration["claimCode"]
print(f"API Key (save now!): {api_key}")
print(f"Claim URL: {registration['claimUrl']}")
Save
apiKeyCodeimmediately — it is only returned once. After the API key is generated, open or clickclaimUrland complete the claim/auth flow. Generating the key alone does not finish agent authentication.
The claimUrl returned by register_agent() is environment-aware and points
directly to the frontend claim page (staging or production). Open it in a
browser to claim and authenticate the agent.
The URL format is:
https://<FRONTEND_DOMAIN>/agents/claim?code=<CLAIM_CODE>
Or use claim_preview(claim_code) to verify the agent name before claiming.
Step 2 — Verify Agent
client = AionMarketClient(api_key=api_key)
me = client.get_me()
print(f"Agent: {me['name']}, Status: {me['status']}")
Step 3 — Derive CLOB Credentials & Register Wallet
The private key is used to call Polymarket's auth endpoint and derive CLOB credentials automatically. The user does not need to manually copy API Key / Secret / Passphrase from Polymarket settings.
import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
load_dotenv()
private_key = os.environ["WALLET_PRIVATE_KEY"]
# 1. Derive CLOB credentials from private key via Polymarket
polymarket = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
)
creds = polymarket.create_or_derive_api_creds()
wallet = polymarket.get_address()
print(f"Wallet: {wallet}")
print(f"CLOB API Key: {creds.api_key}")
# 2. Register with AION Market
check = client.check_wallet_credentials(wallet)
if not check["hasCredentials"]:
client.register_wallet_credentials(
wallet_address=wallet,
api_key=creds.api_key,
api_secret=creds.api_secret,
api_passphrase=creds.api_passphrase,
)
print(f"Wallet credentials registered for {wallet}")
else:
print(f"Wallet {wallet} already configured.")
Step 4 — Configure Risk Limits
client.update_settings(
max_trades_per_day=50,
max_trade_amount=100.0,
trading_paused=False,
auto_redeem_enabled=True,
)
settings = client.get_settings()
print(settings)
Workflow: Market Search & Context
Understanding Market Data Structure
Critical:
get_markets()returns events, each containing a nestedmarkets[]array of sub-markets. Trading fields likeconditionId,clobTokenIds,outcomePrices,negRisk, andorderPriceMinTickSizelive on the sub-market, NOT the event.
import ast
# Search returns events
events = client.get_markets(q="bitcoin", limit=10)
for event in events:
print(f"Event: {event['title']}")
for sub in event.get("markets", []):
# Parse JSON strings
prices = ast.literal_eval(sub.get("outcomePrices", '["0.5","0.5"]'))
token_ids = ast.literal_eval(sub.get("clobTokenIds", '[]'))
print(f" Sub-market: {sub['question']}")
print(f" conditionId: {sub['conditionId']}")
print(f" YES price: {prices[0]}, NO price: {prices[1]}")
print(f" YES token: {token_ids[0] if token_ids else 'N/A'}")
print(f" negRisk: {sub.get('negRisk', False)}")
print(f" tickSize: {sub.get('orderPriceMinTickSize', 0.01)}")
print(f" minSize: {sub.get('orderMinSize', 5)}")
Get Market Context (REQUIRED before trading)
context = client.get_market_context("CONDITION_ID", user=wallet)
market = context.get("market", {})
positions = context.get("positions", {})
safeguards = context.get("safeguards", {})
print(f"Market: {market.get('question') or market.get('title')}")
print(f"Wallet: {positions.get('walletAddress')}")
print(f"Has pos: {positions.get('hasPosition')}")
print(f"Max amount: {safeguards.get('maxTradeAmount')}")
print(f"Warnings: {context.get('warnings')}")
if context.get("warnings"):
print("⚠️ Review warnings before proceeding!")
Automatic Pre-Trade Readiness Checks
Before signing or submitting any order, the agent should automatically verify:
- wallet credentials are already registered, otherwise register them
- collateral balance is sufficient for the intended spend
- Polygon gas balance is sufficient if an onchain approval may be needed
- the required spender allowance already exists for the intended order
If allowance is insufficient and gas is available, the agent should send the approval transaction automatically instead of asking the user to do it manually.
Workflow: Trade Execution
Building a Signed Order (REQUIRED)
The trade() endpoint requires a complete EIP712-signed order from py-clob-client.
Passing "order": {} will cause a credential lookup failure — the server reads
order.signatureType to find your wallet credentials.
import ast
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds, CreateOrderOptions, OrderArgs
# 1. Initialize CLOB client with creds (derived earlier in bootstrap)
clob = ClobClient(
"https://clob.polymarket.com",
key=private_key, # WALLET_PRIVATE_KEY
chain_id=137,
creds=ApiCreds(
api_key=creds.api_key,
api_secret=creds.api_secret,
api_passphrase=creds.api_passphrase,
),
)
# 2. Extract trading params from sub-market (NOT event)
sub_market = event["markets"][0] # pick the sub-market you want to trade
condition_id = sub_market["conditionId"]
token_ids = ast.literal_eval(sub_market["clobTokenIds"])
yes_token_id = token_ids[0] # index 0 = YES, index 1 = NO
no_token_id = token_ids[1]
neg_risk = sub_market.get("negRisk", False)
tick_size = str(sub_market.get("orderPriceMinTickSize", "0.01"))
min_size = sub_market.get("orderMinSize", 5)
# 3. Build signed order — MUST use CreateOrderOptions for proper signing
signed_order = clob.create_order(
OrderArgs(
token_id=yes_token_id, # or no_token_id for NO side
price=0.55,
size=min_size, # must >= orderMinSize
side="BUY",
),
options=CreateOrderOptions(
tick_size=tick_size, # from sub-market.orderPriceMinTickSize
neg_risk=neg_risk, # CRITICAL for neg-risk markets!
),
)
# 4. Convert dataclass to dict for JSON serialization
order_dict = signed_order.dict()
Place a Trade
result = client.trade({
"marketConditionId": condition_id, # hex conditionId from sub-market
"marketQuestion": sub_market["question"], # question text
"outcome": "YES", # YES or NO
"orderSize": min_size, # number of contracts
"price": 0.55, # price per contract (0-1)
"isLimitOrder": True, # True=limit, False=market
"order": order_dict, # ← FULL signed order (never {})
"walletAddress": wallet, # ← REQUIRED
"reasoning": "Strategy edge explanation",
})
print(f"Order ID: {result.get('orderId')}")
print(f"Status: {result.get('status')}")
Default Execution Policy
For general-purpose execution, use this default policy unless the user overrides it:
- prefer
marketmode - use
2USDC as default buy size - derive a marketable cap from current prices or order book when using market-order helpers
- ask for a price only when the user explicitly requested a limit order and did not provide one
- report the market snapshot and final order parameters without blocking on extra confirmation
Common pitfalls:
"order": {}→ server cannot findsignatureType, returns credential error- Using event numeric ID as
marketConditionId→ use sub-market hexconditionId- Missing
walletAddress→ "walletAddress 不能为空" error- Not setting
neg_risk=Truefor neg-risk markets → invalid signature, Polymarket rejectsorderSizebeloworderMinSize→ order rejected- Insufficient USDC balance → server returns generic
INTERNAL_ERROR- Insufficient allowance → downstream exchange cannot spend collateral
- For immediate BUY (
FAK/FOK),makerAmountmust fit max 2 decimals andtakerAmountmax 4 decimals (in 6-decimal micro-units: maker % 10000 == 0, taker % 100 == 0)- SDK result is empty or generic → verify recent trades and orders before reporting failure
Order types: GTC (default), FOK, GTD, FAK
Sides: BUY, SELL
Outcomes: YES, NO
Workflow: Order Management
# List open orders
open_orders = client.get_open_orders()
# Order history (with optional filters)
history = client.get_order_history(limit=20, order_status=2)
# Single order detail
detail = client.get_order_detail("ORDER_ID")
# Cancel one order
client.cancel_order("ORDER_ID")
# Cancel ALL orders (use with care)
client.cancel_all_orders()
Workflow: Heartbeat / Briefing
Call periodically (every 30s–15min depending on strategy frequency).
# wallet = PolymarketClient("https://clob.polymarket.com", key=private_key, chain_id=137).get_address()
briefing = client.get_briefing(user=wallet)
# 1. Handle risk alerts first
for alert in briefing.get("riskAlerts", []):
print(f"⚠️ {alert}")
# 2. Review open orders
open_orders = client.get_open_orders()
print(f"Open orders: {len(open_orders)}")
# 3. Scan opportunity markets
for opp in briefing.get("opportunities", {}).get("newMarkets", [])[:5]:
print(f"Opportunity: {opp.get('id')} — {opp.get('question')}")
Workflow: Redemption
When a market settles, redeem winning positions:
client.redeem(market_id="MARKET_ID", side="YES")
Error Handling
from aionmarket_sdk import AionMarketClient, ApiError
client = AionMarketClient()
try:
result = client.get_me()
except ApiError as e:
if e.status_code == 401:
print("❌ Invalid or missing API key")
elif e.status_code == 403:
print("❌ Agent not authorized — check claim status or wallet credentials")
elif e.status_code == 429:
print("⏳ Rate limited — back off and retry")
else:
print(f"API Error {e.code}: {e.message}")
When trading, an ApiError from AION Market may still hide a successful downstream Polymarket match. If the response is ambiguous, the agent should only do read-only verification (query recent Polymarket trades and open orders) before concluding that the trade failed.
Execution safety rule: never place/cancel orders through direct Polymarket SDK as a fallback. All execution must go through AION endpoints (for example /markets/trade, /markets/orders/cancel, /markets/orders/cancel-all) so risk controls and auditing stay effective.
SDK Method Reference
Agent Management
| Method | Description |
|---|---|
register_agent(name) | Create agent, returns API key + claim code |
claim_preview(claim_code) | Preview agent info via claim code |
get_me() | Current agent profile and balances |
get_settings() | Read risk control settings |
update_settings(...) | Update max trades, max amount, pause, auto-redeem |
get_skills(category, limit, offset) | List available strategy skills |
Market Operations
| Method | Description |
|---|---|
get_markets(q, limit, page, venue, events_status) | Search markets by keyword |
get_market(market_id, venue) | Single market details |
check_market_exists(market_id, venue) | Existence check |
get_prices_history(token_id, ...) | Historical prices for a token |
get_briefing(venue, since, user, include_markets) | Heartbeat: alerts + opportunities |
get_market_context(market_id, venue, user, my_probability) | Pre-trade context & risk |
Wallet Management
| Method | Description |
|---|---|
check_wallet_credentials(wallet_address) | Check if CLOB credentials exist |
register_wallet_credentials(wallet_address, api_key, api_secret, api_passphrase) | Store encrypted CLOB credentials |
Trading Operations
| Method | Description |
|---|---|
trade(payload) | Place a market or limit order |
get_open_orders(venue, market_condition_id, limit) | List unfilled orders |
get_order_history(venue, ..., limit, offset) | Historical orders with filters |
get_order_detail(order_id, venue, wallet_address) | Single order detail |
cancel_order(order_id, venue, wallet_address) | Cancel one order |
cancel_all_orders(venue, wallet_address) | Cancel all open orders |
redeem(market_id, side, venue, wallet_address) | Redeem settled position |
Checklist: Ready to Trade
-
pip install aionmarket-sdk py-clob-client python-dotenvinstalled -
.envfile created withAIONMARKET_API_KEYandWALLET_PRIVATE_KEY -
.envadded to.gitignore -
get_me()returns valid agent info - CLOB credentials derived from private key and registered via
register_wallet_credentials() - automatic balance, gas, and allowance checks are part of the trading flow
- missing allowance is auto-approved when technically possible
- Risk limits configured via
update_settings() - Heartbeat loop (
get_briefing()) running or planned - Error handling wraps every SDK call with
ApiError - ambiguous trade responses are verified against Polymarket trades/orders
Once all boxes are checked, the agent is ready for strategy skills to drive market discovery and automated trade execution.
Comments
Loading comments...
