WebSocket Skill
The xbtfx-websocket skill provides AI agents with read-only access to real-time streaming market quotes and account events over WebSocket.
- Skill name:
xbtfx-websocket - Type: Read-only
- Required env var:
XBTFX_API_KEY - Endpoint:
wss://ws.xbtfx.com/v1/ws
When to Use
Section titled “When to Use”- Stream real-time bid/ask quotes for one or more symbols
- Monitor position, order, and deal events on the account
- Access order book depth data
- Build live dashboards or price alerts
When NOT to Use
Section titled “When NOT to Use”- Executing trades or managing positions. Use the Trading Skill instead.
- Checking account balance or trade history. Use the Account Skill instead.
- One-off symbol lookups. Use the Market Data Skill instead.
Connection and Authentication
Section titled “Connection and Authentication”Connect to the WebSocket endpoint and authenticate within 10 seconds by sending an auth message:
{"action": "auth", "token": "your-api-key"}The server responds with:
{"action": "auth_ok", "login": 12345678, "tier": "standard"}If authentication fails:
{"action": "auth_error", "message": "Invalid API key"}Connection Example (websocat)
Section titled “Connection Example (websocat)”websocat wss://ws.xbtfx.com/v1/ws> {"action":"auth","token":"your-api-key"}< {"action":"auth_ok","login":12345678,"tier":"standard"}> {"action":"subscribe","channel":"quotes","symbols":["BTCUSD"]}< {"channel":"quote","symbol":"BTCUSD","bid":65000.00,"ask":65000.50,"spread":50,"time":"2025-01-15T10:30:00.123Z"}Connection Example (Python)
Section titled “Connection Example (Python)”import asyncioimport jsonimport websockets
async def stream_quotes(): uri = "wss://ws.xbtfx.com/v1/ws" async with websockets.connect(uri) as ws: # Authenticate await ws.send(json.dumps({ "action": "auth", "token": "your-api-key" })) auth_response = await ws.recv() print(auth_response)
# Subscribe to quotes await ws.send(json.dumps({ "action": "subscribe", "channel": "quotes", "symbols": ["BTCUSD"] }))
# Receive messages async for message in ws: data = json.loads(message) print(data)
asyncio.run(stream_quotes())Channels
Section titled “Channels”Quotes Channel
Section titled “Quotes Channel”Subscribe to real-time bid/ask quotes for a symbol.
Subscribe:
{"action": "subscribe", "channel": "quotes", "symbols": ["BTCUSD"]}With depth (order book):
{"action": "subscribe", "channel": "quotes", "symbols": ["BTCUSD"], "depth": true}Unsubscribe:
{"action": "unsubscribe", "channel": "quotes", "symbols": ["BTCUSD"]}Quote message:
{ "channel": "quote", "symbol": "BTCUSD", "bid": 65000.00, "ask": 65000.50, "spread": 50, "time": "2025-01-15T10:30:00.123Z"}Quote message with depth (when depth is enabled):
When depth is enabled, the order book data is nested within the quote message:
{ "channel": "quote", "symbol": "BTCUSD", "bid": 65000.00, "ask": 65000.50, "spread": 50, "depth": { "bids": [[65000.00, 1.5], [64999.50, 2.0]], "asks": [[65000.50, 1.2], [65001.00, 3.0]] }, "time": "2025-01-15T10:30:00.123Z"}Account Channel
Section titled “Account Channel”Subscribe to real-time account events including position, order, and deal updates.
Subscribe:
{"action": "subscribe", "channel": "account"}Position event:
{ "type": "position", "event": "open", "ticket": 12345678, "symbol": "BTCUSD", "side": "buy", "volume": 0.01, "price": 65000.00}Order event:
{ "type": "order", "event": "placed", "ticket": 12345679, "symbol": "BTCUSD", "order_type": "buy_limit", "volume": 0.01, "price": 64000.00}Deal event:
{ "type": "deal", "event": "filled", "ticket": 12345680, "symbol": "BTCUSD", "side": "buy", "volume": 0.01, "price": 65000.00, "profit": 0.00}System Messages
Section titled “System Messages”The server may send system messages for connection state changes:
{"channel": "system", "event": "connected"}{"channel": "system", "event": "reconnect_required"}Keepalive
Section titled “Keepalive”- Send
{"action": "ping"}every 30 seconds to keep the connection alive - The server responds with
{"action": "pong"} - The server closes idle connections after 90 seconds without any messages
Connection Limits
Section titled “Connection Limits”| Limit | Value |
|---|---|
| Max connections per API key | 10 |
| Max symbol subscriptions per connection | 1,000 |
| Quote throttle rate | 5 updates/sec per symbol |
Error Codes
Section titled “Error Codes”| Code | Description |
|---|---|
auth_error | Authentication failed: invalid or expired token |
subscription_limit | Subscription limit reached (max 1,000 symbols per connection) |
connection_limit | Maximum connection count exceeded |
rate_limited | Message rate limit exceeded |
Error messages are sent as JSON:
{"type": "error", "code": "subscription_limit", "message": "Maximum subscriptions reached (1000 per connection)"}Agent Guidelines
Section titled “Agent Guidelines”Agents using this skill must follow these behavioral rules:
- This is a read-only skill. WebSocket connections cannot execute trades or modify account state.
- Authenticate immediately. Send the auth message within 10 seconds of connecting.
- Implement keepalive. Send
{"action": "ping"}every 30 seconds to prevent idle disconnection. - Unsubscribe when done. Remove subscriptions that are no longer needed to stay within limits.
- Handle reconnection gracefully. If the connection drops, reconnect and re-authenticate. Resubscribe to all previously active channels.
- Always mask API keys in output. Never display the full API key or auth token to the user.
- Respect subscription limits. Do not subscribe to more than 1,000 symbols per connection.
- Process messages asynchronously. Quote updates arrive at up to 5 per second per symbol. Ensure the agent processes or buffers messages without blocking the connection.