Async Client
AsyncAgentExchangeClient — async/await Python client for concurrent agents
AsyncAgentExchangeClient is the async counterpart to AgentExchangeClient. It exposes an identical API surface of 37 methods — every method is an async def that must be awaited.
When to Use Async vs Sync
- Running multiple agent tasks in parallel with
asyncio.gather - Building a FastAPI or other async web service that serves agent requests
- Integrating with async frameworks like LangGraph or any
asyncio-based tool - You need high throughput from a single process (many concurrent HTTP calls)
- Writing a straightforward trading script that runs one task at a time
- Integrating with synchronous frameworks like LangChain's
Toolor CrewAI's@tool - The simplicity of
client.get_price("BTCUSDT")is preferable toawait client.get_price("BTCUSDT")
Import and Construction
from agentexchange import AsyncAgentExchangeClient
# Context manager — recommended
async with AsyncAgentExchangeClient(
api_key="ak_live_...",
api_secret="sk_live_...",
base_url="http://localhost:8000", # default
timeout=30.0, # default
) as client:
price = await client.get_price("BTCUSDT")
print(price.price)
Or construct and close manually:
client = AsyncAgentExchangeClient(
api_key="ak_live_...",
api_secret="sk_live_...",
)
try:
price = await client.get_price("BTCUSDT")
finally:
await client.close()
Basic Usage
All methods are identical to the sync client, with await added:
import asyncio
import os
from decimal import Decimal
from dotenv import load_dotenv
from agentexchange import AsyncAgentExchangeClient
load_dotenv()
async def main():
async with AsyncAgentExchangeClient(
api_key=os.environ["AGENTEXCHANGE_API_KEY"],
api_secret=os.environ["AGENTEXCHANGE_API_SECRET"],
) as client:
# Fetch live price
price = await client.get_price("BTCUSDT")
print(f"BTC: ${price.price}")
# Check balance before ordering
balance = await client.get_balance()
print(f"Available USDT: {balance.balances[0].available}")
# Place a market order
order = await client.place_market_order(
symbol="BTCUSDT",
side="buy",
quantity=Decimal("0.001"),
)
print(f"Order {order.order_id}: {order.status}")
# Check portfolio
portfolio = await client.get_portfolio()
print(f"Total equity: ${portfolio.total_equity} ROI: {portfolio.roi_pct}%")
asyncio.run(main())
Running Multiple Tasks Concurrently
The async client shines when you need to make several independent calls simultaneously. Use asyncio.gather to run them in parallel instead of sequentially:
import asyncio
from agentexchange import AsyncAgentExchangeClient
async def fetch_market_snapshot(client, symbol: str) -> dict:
"""Fetch price and 24h ticker for one symbol concurrently."""
price, ticker = await asyncio.gather(
client.get_price(symbol),
client.get_ticker(symbol),
)
return {
"symbol": symbol,
"price": str(price.price),
"change_24h": str(ticker.change_pct),
"volume": str(ticker.volume),
}
async def main():
async with AsyncAgentExchangeClient(
api_key=os.environ["AGENTEXCHANGE_API_KEY"],
api_secret=os.environ["AGENTEXCHANGE_API_SECRET"],
) as client:
# Fetch snapshots for 5 coins simultaneously
symbols = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "ADAUSDT"]
snapshots = await asyncio.gather(
*[fetch_market_snapshot(client, s) for s in symbols]
)
for snap in snapshots:
print(f"{snap['symbol']}: ${snap['price']} ({snap['change_24h']}%)")
asyncio.run(main())
Compared to the sync client, this reduces latency from 5 × request_time to 1 × request_time.
Running Multiple Independent Agent Tasks
import asyncio
from agentexchange import AsyncAgentExchangeClient
async def run_agent_task(client, task_description: str) -> str:
"""Stub for an agent task that uses the client."""
portfolio = await client.get_portfolio()
return f"Task '{task_description}' — equity: ${portfolio.total_equity}"
async def run_concurrent_agents():
async with AsyncAgentExchangeClient(
api_key=os.environ["AGENTEXCHANGE_API_KEY"],
api_secret=os.environ["AGENTEXCHANGE_API_SECRET"],
) as client:
tasks = [
"What is the current BTC price?",
"What is my portfolio value?",
"List my open orders.",
"What were my last 5 trades?",
"What is my 7-day Sharpe ratio?",
]
results = await asyncio.gather(
*[run_agent_task(client, t) for t in tasks]
)
for result in results:
print(result)
asyncio.run(run_concurrent_agents())
Using with FastAPI
When building an API service that runs agent operations as async tasks:
import asyncio
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from agentexchange import AsyncAgentExchangeClient
# Shared client held for the lifetime of the application
_client: AsyncAgentExchangeClient | None = None
@asynccontextmanager
async def lifespan(app: FastAPI):
global _client
_client = AsyncAgentExchangeClient(
api_key=os.environ["AGENTEXCHANGE_API_KEY"],
api_secret=os.environ["AGENTEXCHANGE_API_SECRET"],
)
yield
await _client.close()
app = FastAPI(lifespan=lifespan)
@app.get("/portfolio")
async def get_portfolio():
portfolio = await _client.get_portfolio()
return {
"total_equity": str(portfolio.total_equity),
"roi_pct": str(portfolio.roi_pct),
}
@app.post("/order")
async def place_order(symbol: str, side: str, quantity: str):
from decimal import Decimal
order = await _client.place_market_order(
symbol=symbol,
side=side,
quantity=Decimal(quantity),
)
return {"order_id": str(order.order_id), "status": order.status}
Error Handling in Async Code
Exception handling is identical to the sync client — the same exception classes are raised:
import asyncio
import time
from agentexchange import AsyncAgentExchangeClient
from agentexchange.exceptions import (
InsufficientBalanceError,
RateLimitError,
InvalidSymbolError,
AgentExchangeError,
)
async def safe_buy(client, symbol: str, quantity: str):
from decimal import Decimal
try:
order = await client.place_market_order(
symbol=symbol,
side="buy",
quantity=Decimal(quantity),
)
return order
except InsufficientBalanceError as e:
print(f"Need {e.required} USDT, only have {e.available}")
return None
except RateLimitError as e:
wait = e.retry_after or 60
print(f"Rate limited — waiting {wait}s")
await asyncio.sleep(wait)
return await safe_buy(client, symbol, quantity) # one retry
except InvalidSymbolError as e:
print(f"Unknown symbol: {e.symbol}")
return None
except AgentExchangeError as e:
print(f"Error {e.code}: {e}")
return None
The sync and async clients share no base class — the duplication is intentional to avoid runtime complexity. Every method on AgentExchangeClient has an identical async def version on AsyncAgentExchangeClient.
Full Method Reference
The async client exposes the exact same 37 methods as the sync client. See the Sync Client reference for the complete list — prefix each call with await.
# Sync
price = client.get_price("BTCUSDT")
# Async
price = await client.get_price("BTCUSDT")
Further Reading
- Sync Client — full method reference with examples
- WebSocket Client — real-time streaming (always async)
- Error Handling — exception hierarchy and retry patterns