When an AI assistant responds to "What's the current price of NVDA?" with a precise, sourced figure, something non-obvious happened under the hood. The model didn't hallucinate the number — it invoked a tool. That tool invocation is governed by a specification file that lives at a predictable URL and defines, in machine-readable form, exactly what capabilities an AI can request on your behalf.

This layer — the protocol bridging AI intent and API execution — is where most integration guides fall silent. They tell you the endpoint exists. They rarely tell you how the AI decides when and how to call it.

This article dissects that layer. We will walk through the structure of the specification file that makes this possible, explain how AI models parse it at runtime, and demonstrate exactly how Function Calling maps to market data queries.


The Core Problem: AI Models Don't Know Your API

Large language models are trained on text. They generate plausible responses — but they have no native mechanism to query live data, authenticate against a private API, or handle rate limits. When you ask an AI "Show me the order book depth for AAPL," the model cannot reach out and fetch that information on its own.

The solution is tool-augmented generation, often implemented via the Function Calling specification popularized by OpenAI's API and now adopted across major model providers including Anthropic, Google Gemini, and open-source alternatives.

The challenge is that Function Calling requires a contract. The AI needs to know:

  • What tools exist (and what they're called)
  • What parameters each tool accepts
  • What the expected response format looks like
  • Which scenarios warrant invoking each tool

Without a standardized, versioned specification file, every AI integration becomes a bespoke engineering project. You write custom wrapper code, maintain parallel documentation, and pray that the AI interprets your descriptions correctly.

The SKILL protocol solves this by codifying the contract into a single file that lives alongside your API — discoverable, versionable, and parseable by any compliant AI runtime.


SKILL.md: The Specification File Structure

The specification file is named skill.md and is served at a well-known URL within your API's domain. For TickDB, this file lives at https://api.tickdb.ai/skill.md.

The file is structured in YAML frontmatter followed by Markdown content. The frontmatter declares metadata; the body describes capabilities, parameters, and behavioral expectations.

Metadata Block

---
name: tickdb-market-data
version: 1.0.0
description: Real-time and historical market data for stocks, crypto, forex, and commodities via WebSocket and REST
api_endpoint: https://api.tickdb.ai/v1
protocol: skill.md
---

The name field identifies the skill to AI runtimes. The version field enables backward compatibility — when you deploy a breaking change, existing AI integrations continue working until they opt into the new version. The protocol field declares which specification version this file conforms to.

Capability Declaration

The body of skill.md lists available functions grouped by category. Each function entry follows a consistent schema:

## Functions

### get_stock_quote
Get real-time quotes for US and Hong Kong equities.

**Endpoint**: `GET /v1/market/quote`
**Authentication**: Header `X-API-Key`

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| symbol | string | Yes | Exchange-coded symbol, e.g., `AAPL.US` or `TSLA.US` |
| fields | string[] | No | Specific fields to return; defaults to all available fields |

**Example Request**:
```http
GET /v1/market/quote?symbol=AAPL.US HTTP/1.1
Host: api.tickdb.ai
X-API-Key: {{TICKDB_API_KEY}}

Example Response:

{
  "code": 0,
  "data": {
    "symbol": "AAPL.US",
    "last_price": 182.45,
    "bid": 182.44,
    "ask": 182.46,
    "volume": 54230000,
    "timestamp": 1719426000000
  }
}

Error Codes:

Code Meaning Handling
1001 Invalid API key Verify TICKDB_API_KEY environment variable
2002 Symbol not found Check symbol format; verify via /v1/symbols/available
3001 Rate limit Respect Retry-After header; implement exponential backoff

get_historical_klines

Retrieve OHLCV (candlestick) data for backtesting and analysis.

Endpoint: GET /v1/market/kline
Authentication: Header X-API-Key

Parameter Type Required Description
symbol string Yes Exchange-coded symbol
interval string Yes Candle interval: 1m, 5m, 15m, 1h, 4h, 1d, 1w
start_time integer Yes Unix timestamp in milliseconds
end_time integer Yes Unix timestamp in milliseconds
limit integer No Maximum records to return (default 100, max 1000)

Example Request:

GET /v1/market/kline?symbol=AAPL.US&interval=1h&start_time=1719339600000&end_time=1719426000000&limit=24 HTTP/1.1
Host: api.tickdb.ai
X-API-Key: {{TICKDB_API_KEY}}

Example Response:

{
  "code": 0,
  "data": [
    {
      "symbol": "AAPL.US",
      "open": 181.20,
      "high": 183.15,
      "low": 180.95,
      "close": 182.45,
      "volume": 12450000,
      "timestamp": 1719343200000
    }
  ]
}

Notes:

  • Use GET /v1/market/kline/latest for the current in-progress candle.
  • Historical data is cleaned and aligned across venues.
  • US equity historical OHLCV covers 10+ years.
  • trades endpoint does not support US equities or A-shares.

### subscribe_depth
Subscribe to real-time order book depth via WebSocket.

**Protocol**: WebSocket
**Endpoint**: `wss://api.tickdb.ai/v1/ws`
**Authentication**: URL parameter `api_key`

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| channel | string | Yes | Set to `"depth"` |
| symbol | string | Yes | Exchange-coded symbol |
| levels | integer | No | Number of price levels (default 1; US equities: L1 only) |

**WebSocket Subscription Message**:
```json
{
  "cmd": "subscribe",
  "params": {
    "channel": "depth",
    "symbol": "AAPL.US",
    "levels": 1
  }
}

WebSocket Response (Depth Update):

{
  "symbol": "AAPL.US",
  "bids": [[182.44, 1200], [182.43, 3500]],
  "asks": [[182.46, 800], [182.47, 2100]],
  "timestamp": 1719426000500
}

Notes:

  • WebSocket authentication uses URL parameter ?api_key=, not a header.
  • Include a heartbeat: {"cmd": "ping"} every 30 seconds.
  • Implement reconnection with exponential backoff and jitter.
  • US equities support L1 depth only; HK equities and crypto support up to L10.

---

## How AI Models Parse the Specification

When an AI runtime receives a user query, it performs a structured process to determine whether tool invocation is appropriate.

### Step 1: Capability Matching

The AI model reads the `skill.md` file during initialization or when it encounters an unfamiliar domain. It builds an internal map of available functions, their parameters, and their descriptions.

The descriptions are critical. They are what the model uses to decide whether a given function is relevant to the user's request. A description like "Get real-time quotes for US and Hong Kong equities" tells the model to invoke this function when the user asks about stock prices. A vaguer description like "Fetch market data" would cause the model to guess — often incorrectly.

The SKILL protocol standardizes description quality by requiring each function entry to include:

- A clear, one-sentence purpose statement
- A list of parameters with types and constraints
- Example requests and responses
- Error code documentation

### Step 2: Parameter Extraction

Once the model selects a function, it must extract parameter values from the user's natural language query.

For the query "What's the current price of AAPL?", the model:

1. Identifies `get_stock_quote` as the relevant function
2. Extracts `AAPL.US` as the `symbol` parameter (with knowledge that AAPL is a US equity)
3. Determines no `fields` override is needed (use defaults)
4. Generates a function call payload

```json
{
  "name": "get_stock_quote",
  "parameters": {
    "symbol": "AAPL.US"
  }
}

Step 3: Execution and Response Injection

The AI runtime executes the function call — typically by making an HTTP request to the API endpoint specified in skill.md. The API response is injected back into the conversation context as a special message type that the model can reference.

The model then generates a natural language response that incorporates the retrieved data, cites the source, and provides context.

Step 4: Error Handling

When the API returns an error, the model must decide how to respond. The SKILL protocol addresses this by documenting error codes explicitly in the specification file. The model learns to map error codes to user-facing messages:

Error scenario Model's response
1001 (invalid API key) "I encountered an authentication error. Please verify your API key is set correctly in the TICKDB_API_KEY environment variable."
2002 (symbol not found) "The symbol 'XYZ' was not found. Please check the symbol format — for US equities, use the format AAPL.US."
3001 (rate limit) "The data provider is rate-limiting requests. I will retry with a delay."

Function Calling in Practice: A Multi-Turn Conversation

To illustrate the full cycle, consider a multi-turn conversation:

User: "What's the current price of AAPL?"

AI (model): Detects the query maps to get_stock_quote with symbol: AAPL.US. Generates a function call.

{
  "name": "get_stock_quote",
  "parameters": {
    "symbol": "AAPL.US"
  }
}

AI runtime: Executes GET /v1/market/quote?symbol=AAPL.US against https://api.tickdb.ai/v1. Receives:

{
  "code": 0,
  "data": {
    "symbol": "AAPL.US",
    "last_price": 182.45,
    "bid": 182.44,
    "ask": 182.46,
    "volume": 54230000,
    "timestamp": 1719426000000
  }
}

AI (model): Generates response: "AAPL.US is currently trading at $182.45, with a bid of $182.44 and an ask of $182.46. The 24-hour volume is approximately 54.2 million shares. (Source: TickDB real-time quote)"


User: "Show me the hourly chart for the last 24 hours."

AI (model): Detects the query maps to get_historical_klines with the appropriate time window. Calculates start_time and end_time from the current timestamp.

{
  "name": "get_historical_klines",
  "parameters": {
    "symbol": "AAPL.US",
    "interval": "1h",
    "start_time": 1719339600000,
    "end_time": 1719426000000,
    "limit": 24
  }
}

AI runtime: Executes the request. Receives 24 hourly candles.

AI (model): Generates a natural language summary of the price action, possibly accompanied by a rendered chart or a textual representation of the data.


User: "Alert me if AAPL's price drops below $180."

AI (model): Detects this is a threshold alert, which requires continuous monitoring. Since the SKILL protocol as documented here does not include a native alerting function, the model explains the limitation and suggests the user implement a WebSocket subscription to the depth or quote channel with a client-side threshold check.

import os
import json
import time
import random
import websocket
import requests

# Load API key from environment
API_KEY = os.environ.get("TICKDB_API_KEY")
if not API_KEY:
    raise ValueError("TICKDB_API_KEY environment variable is not set")

# Configuration
SYMBOL = "AAPL.US"
ALERT_THRESHOLD = 180.00
WS_URL = f"wss://api.tickdb.ai/v1/ws?api_key={API_KEY}"
RECONNECT_BASE_DELAY = 1
RECONNECT_MAX_DELAY = 32

def on_message(ws, message):
    """Handle incoming WebSocket messages."""
    data = json.loads(message)
    
    # Handle pong (heartbeat response)
    if data.get("cmd") == "pong":
        return
    
    # Parse quote data
    if "last_price" in data:
        price = float(data["last_price"])
        timestamp = data.get("timestamp", 0)
        
        print(f"[{timestamp}] {SYMBOL}: ${price:.2f}")
        
        if price < ALERT_THRESHOLD:
            print(f"🚨 ALERT: {SYMBOL} dropped below ${ALERT_THRESHOLD}! Current price: ${price:.2f}")
            # In production: send Slack notification, email, etc.

def on_error(ws, error):
    """Log errors without crashing."""
    print(f"WebSocket error: {error}")

def on_close(ws, close_status_code, close_msg):
    """Handle connection closure."""
    print(f"Connection closed (code: {close_status_code})")

def on_open(ws):
    """Subscribe to quote channel on connection open."""
    subscribe_message = json.dumps({
        "cmd": "subscribe",
        "params": {
            "channel": "quote",
            "symbol": SYMBOL
        }
    })
    ws.send(subscribe_message)
    print(f"Subscribed to {SYMBOL} quote channel")

def send_heartbeat(ws):
    """Send periodic heartbeat to keep connection alive."""
    ws.send(json.dumps({"cmd": "ping"}))

def run_with_reconnect():
    """Run WebSocket client with automatic reconnection."""
    retry_count = 0
    
    while True:
        ws = websocket.WebSocketApp(
            WS_URL,
            on_message=on_message,
            on_error=on_error,
            on_close=on_close,
            on_open=on_open
        )
        
        try:
            # Run with heartbeat thread
            import threading
            
            def heartbeat_loop():
                while True:
                    time.sleep(30)
                    try:
                        send_heartbeat(ws)
                    except Exception:
                        break
            
            heartbeat_thread = threading.Thread(target=heartbeat_loop, daemon=True)
            heartbeat_thread.start()
            
            ws.run_forever()
            
        except Exception as e:
            print(f"WebSocket error: {e}")
        
        # Exponential backoff with jitter
        retry_count += 1
        delay = min(RECONNECT_BASE_DELAY * (2 ** retry_count), RECONNECT_MAX_DELAY)
        jitter = random.uniform(0, delay * 0.1)
        wait_time = delay + jitter
        
        print(f"Reconnecting in {wait_time:.2f} seconds (attempt {retry_count})...")
        time.sleep(wait_time)

if __name__ == "__main__":
    print(f"Starting price alert for {SYMBOL}")
    print(f"Alert threshold: ${ALERT_THRESHOLD}")
    run_with_reconnect()

This code implements a production-grade WebSocket client with:

  • Heartbeat: Sends {"cmd": "ping"} every 30 seconds to prevent connection timeout.
  • Exponential backoff with jitter: On reconnection, delays double each attempt (1s, 2s, 4s, ... up to 32s) plus random jitter to prevent thundering herd.
  • Environment-variable auth: API key loaded from TICKDB_API_KEY, never hardcoded.
  • Graceful error handling: Logs errors without crashing; reconnects automatically.
  • Alert logic: Client-side threshold check on each incoming quote update.

The Value of a Standardized Skill Specification

The SKILL protocol addresses a real engineering problem: the impedance mismatch between natural language queries and API calls.

Without a standardized specification:

  • Every AI integration requires custom prompt engineering
  • Model behavior is unpredictable across different queries
  • API changes break AI integrations silently
  • Error handling is ad hoc and inconsistent

With a standardized specification:

  • The contract is explicit, versioned, and machine-readable
  • Model behavior is deterministic given the same specification
  • API changes are captured in version bumps, enabling migration
  • Error codes map directly to user-facing messages

For developers building AI-augmented trading interfaces, the SKILL protocol means you can focus on the application layer — dashboards, alerts, strategy automation — without re-implementing the AI-to-API bridge for every new capability.


Next Steps

If you're a developer integrating AI into a trading workflow, review the full skill.md specification at your data provider's API endpoint to understand the complete function catalog available to your AI runtime.

If you want to test the integration today, sign up at tickdb.ai to obtain a free API key, then use the WebSocket code above as a starting point. The free tier provides access to real-time quotes and depth data for a subset of symbols.

If you're building a multi-agent system, the SKILL protocol's versioned specification makes it straightforward to pin agents to specific capability versions, enabling controlled rollouts of new API features.

If you use AI coding assistants, search for and install the tickdb-market-data SKILL in your AI tool's marketplace to enable direct market data queries from within your development environment.


This article does not constitute investment advice. Markets involve risk; past performance does not guarantee future results.