When an AI assistant responds to a user's query about NVIDIA's after-hours volatility, it needs more than a vague description of your API. It needs a precise contract: what parameters exist, what data types are expected, what errors can occur, and how to handle pagination. That contract lives in a single file: skill.md.
This article dissects the TickDB SKILL protocol specification — its structure, how AI models parse it at runtime, and how Function Calling definitions enable reliable, multi-turn conversations about market data.
What the SKILL Protocol Is
The SKILL protocol is TickDB's machine-readable specification format designed for AI integration. At its core, it is a Markdown file with a structured YAML frontmatter block that AI assistants can parse to understand:
- Which API endpoints are available
- What each endpoint does and what parameters it accepts
- What response shapes look like
- How to handle errors and pagination
- What context the AI should maintain across conversation turns
The protocol gets its name from the ecosystem it targets: AI agent "skills" — modular capabilities that extend an AI assistant's ability to interact with external systems. When you install the tickdb-market-data SKILL on ClawHub or an equivalent AI marketplace, you are distributing this specification alongside execution instructions.
Unlike OpenAPI (Swagger) specifications, which prioritize human-readable documentation and HTTP transport semantics, the SKILL protocol is optimized for prompt injection efficiency. Each endpoint definition includes not just the technical schema but also the conversational context in which that endpoint becomes relevant. This matters because a general-purpose AI model, when given only raw OpenAPI specs, often misinterprets parameter semantics in financial contexts.
The skill.md File Structure
A TickDB SKILL file contains three primary sections:
Section 1: Frontmatter
The frontmatter uses YAML to define metadata that AI parsers read before processing the rest of the file:
---
name: tickdb-market-data
version: "1.2.0"
description: Real-time and historical market data from TickDB
provider: TickDB
homepage: https://tickdb.ai
documentation: https://docs.tickdb.ai
icon: https://tickdb.ai/icon.png
installations: >
pip install tickdb-market-data
npm install @tickdb/market-data-sdk
languages:
- python
- typescript
- javascript
categories:
- market-data
- finance
- trading
triggers:
- "What is the price of {symbol}?"
- "Get me the order book for {symbol}"
- "Historical data for {symbol} from {start_date} to {end_date}"
scopes:
- read-market-data
- read-historical-klines
- subscribe-depth-stream
---
The triggers field is particularly important. These are natural-language patterns that, when matched by the AI, activate the corresponding SKILL. The curly-brace syntax indicates slots — variables the AI extracts from the user's utterance.
Section 2: Function Definitions
After the frontmatter, the SKILL file lists each callable function with structured metadata:
## functions
### get_kline
**Description**: Retrieve historical OHLCV (candlestick) data for a given symbol and time range. Use this when the user wants to analyze price history, backtest a strategy, or understand long-term trends.
**Parameters**:
| Name | Type | Required | Description |
|------|------|----------|-------------|
| symbol | string | Yes | Trading symbol in `{TICKER}.{EXCHANGE}` format (e.g., `NVDA.US`, `BTC.Binance`) |
| interval | enum | Yes | Candle interval: `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`, `1w`, `1M` |
| start_time | integer | No | Unix timestamp in milliseconds. Defaults to 24 hours ago if not specified. |
| end_time | integer | No | Unix timestamp in milliseconds. Defaults to current time if not specified. |
| limit | integer | No | Number of candles to return. Range: 1–1000. Defaults to 100. |
**Response Shape**:
```json
{
"code": 0,
"message": "success",
"data": [
{
"t": 1735689600000,
"o": 142.50,
"h": 145.20,
"l": 141.80,
"c": 144.10,
"v": 45678900
}
]
}
Error Codes:
| Code | Condition | Recovery |
|---|---|---|
| 1001 | Invalid API key | Check TICKDB_API_KEY environment variable |
| 2002 | Symbol not found | Verify symbol via get_available_symbols |
| 3001 | Rate limit exceeded | Respect Retry-After header, retry after delay |
Usage Example:
User: Show me AAPL's hourly data for the last week
AI: get_kline(symbol="AAPL.US", interval="1h", limit=168)
Each function definition follows a consistent template: description (with conversational context), parameter table (with types and constraints), response shape, error codes with recovery instructions, and a natural-language usage example.
### Section 3: Conversation State Schema
For multi-turn conversations, the SKILL file defines what context the AI should maintain:
```markdown
## conversation_state
The AI should maintain the following state across turns:
| State Key | Type | Description |
|-----------|------|-------------|
| current_symbol | string | The symbol the user is currently querying |
| current_timeframe | string | The interval last used (e.g., "1h", "1d") |
| last_response | object | The most recent API response for reference |
| user_preferences | object | Cached preferences like default exchange or timezone |
**State Transitions**:
- When the user mentions a new symbol, update `current_symbol`
- When the user changes the time range, update `current_timeframe` and reset `last_response`
- When the user asks a follow-up about the same data, reference `last_response` before making a new API call
This state management prevents redundant API calls. If a user asks "What was the closing price?" after the AI has already fetched kline data, the AI reads last_response instead of making a second request.
How AI Parses the Specification
At runtime, the AI does not read the entire skill.md file for every turn. Instead, it follows a three-phase parsing strategy:
Phase 1: Trigger Matching
When a user sends a message, the AI compares it against the trigger patterns in the frontmatter. This is a lightweight pattern match using keyword and intent classification. If the message scores above a threshold for any trigger, the SKILL activates.
For example:
- User says: "What's the bid-ask spread on TSLA right now?"
- AI matches
triggers→ activatestickdb-market-dataSKILL - AI extracts
TSLAas the symbol parameter
Phase 2: Function Selection
Once activated, the AI reads the function definitions that are relevant to the detected intent. It does not load every function — it performs a second classification pass:
- Does the user want historical data? → Load
get_kline - Does the user want real-time depth? → Load
subscribe_depth - Is the user asking about available symbols? → Load
get_available_symbols
Phase 3: Parameter Extraction and Validation
The AI extracts parameters from the user's message using the slot definitions in the trigger patterns and the parameter tables in the function definitions. It validates:
- Type correctness: The symbol is a string, the limit is an integer
- Required fields:
symbolandintervalare mandatory forget_kline - Range constraints:
limitmust be between 1 and 1000 - Format compliance: Symbols must follow the
{TICKER}.{EXCHANGE}convention
If validation fails, the AI returns a clarification to the user rather than making a malformed API call.
Function Calling Definition
Function Calling in the SKILL protocol maps natural-language requests to structured API calls. The definition goes beyond a simple parameter list — it includes semantic annotations that tell the AI how to behave in edge cases.
Parameter Annotations
**Parameters**:
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| symbol | string | Yes | — | Trading pair. Format: `{TICKER}.{EXCHANGE}` |
| limit | integer | No | 100 | Max results. Range: 1–1000 |
| interval | enum | No | "1d" | Candle interval. Enum: 1m/5m/15m/30m/1h/4h/1d/1w |
The Default column guides the AI when the user does not specify a value. The Enum column on interval tells the AI to constrain its output to the listed options — it should not generate arbitrary strings like "2h" or "daily."
Response Mapping
The AI does not dump raw JSON into the conversation. The SKILL file instructs it how to format responses for different user intents:
**Response Presentation**:
- If user asks for "current price": Return `c` (close) as a single number with currency
- If user asks for "high/low": Return `h` and `l` with timestamps
- If user asks for "volume": Return `v` formatted with thousands separators
- If user asks for "full candle data": Return a formatted table with all OHLCV fields
This instruction layer is what distinguishes a useful AI response from a raw API dump.
Error Handling Flows
Function definitions include explicit error recovery paths:
**On code 3001 (Rate Limit)**:
1. Read the `Retry-After` header from the response
2. Wait for that duration
3. Retry the request once
4. If the retry fails, inform the user: "TickDB's rate limit was reached.
Please wait 30 seconds before trying again."
**On code 2002 (Symbol Not Found)**:
1. Call `get_available_symbols()` to retrieve the list of valid symbols
2. Present the list to the user: "The symbol you requested is not available.
Here are similar symbols that are supported: {list}"
Without these recovery instructions, an AI would either hallucinate a response or crash silently on error.
Multi-Turn Conversation Flow
The SKILL protocol supports multi-turn conversations through explicit state management and turn-taking rules.
Example Conversation
User (Turn 1): What's the current price of NVDA?
AI:
Tool: get_kline(symbol="NVDA.US", interval="1d", limit=1)
→ Response: {"c": 142.85}
Response to user: "NVIDIA (NVDA.US) is currently trading at $142.85."
State update: {current_symbol: "NVDA.US", current_interval: "1d"}
---
User (Turn 2): Show me the last five days.
AI:
State check: current_symbol = "NVDA.US", current_interval = "1d"
Tool: get_kline(symbol="NVDA.US", interval="1d", limit=5)
→ Response: 5 candles
Response to user: "Here are NVDA's closing prices for the last 5 trading days:
| Date | Close |
|----------|---------|
| Nov 28 | $138.20 |
| Nov 29 | $140.50 |
| Dec 2 | $139.80 |
| Dec 3 | $141.90 |
| Dec 4 | $142.85 |
---
User (Turn 3): What was the trading range on Dec 2?
AI:
State check: current_symbol = "NVDA.US"
Filter response from Turn 2: Dec 2 candle has h=141.20, l=138.90
Response to user: "On December 2, NVDA traded between a low of $138.90
and a high of $141.20 — a range of $2.30."
No new API call was made for Turn 3. The AI reasoned over the cached last_response from Turn 2.
Code Example: SKILL File Consumption
For developers integrating the SKILL protocol programmatically, here is a Python example that parses a skill.md file and extracts function definitions:
import re
import yaml
from typing import Dict, List, Optional
class SkillParser:
"""Parse a TickDB skill.md file into structured function definitions."""
def __init__(self, skill_content: str):
self.raw_content = skill_content
self.frontmatter = self._parse_frontmatter()
self.functions = self._parse_functions()
self.conversation_state = self._parse_conversation_state()
def _parse_frontmatter(self) -> dict:
"""Extract YAML frontmatter from the skill.md file."""
match = re.match(r'^---\n(.*?)\n---\n', self.raw_content, re.DOTALL)
if not match:
raise ValueError("Invalid skill.md: missing YAML frontmatter")
return yaml.safe_load(match.group(1))
def _parse_functions(self) -> List[Dict]:
"""Extract function definitions from Markdown content."""
functions = []
func_pattern = re.compile(
r'^### (\w+)\s*\n\*\*Description\*\*: (.+?)\n\*\*Parameters\*\*:.*?'
r'(\| Name.*?\n\|[^\n]+\n(?:\|[^\n]+\n)*)',
re.MULTILINE | re.DOTALL
)
for match in func_pattern.finditer(self.raw_content):
name = match.group(1)
description = match.group(2)
param_table = match.group(3)
functions.append({
"name": name,
"description": description,
"parameters": self._parse_parameter_table(param_table)
})
return functions
def _parse_parameter_table(self, table: str) -> List[Dict]:
"""Parse a Markdown parameter table into structured data."""
rows = re.findall(r'\|\s*(\w+)\s*\|\s*(\w+)\s*\|\s*(\w+)\s*\|', table)
return [
{"name": row[0], "type": row[1], "required": row[2] == "Yes"}
for row in rows
]
def _parse_conversation_state(self) -> Dict:
"""Extract conversation state schema."""
state_pattern = re.compile(
r'\*\*State Key\*\*.*?\n\|.*?\|.*?\|\n((?:\|[^\n]+\n)*)',
re.DOTALL
)
match = state_pattern.search(self.raw_content)
if not match:
return {}
rows = re.findall(r'\|\s*(\w+)\s*\|\s*(\w+)\s*\|', match.group(1))
return {row[0]: row[1] for row in rows}
def get_function(self, name: str) -> Optional[Dict]:
"""Retrieve a function definition by name."""
for func in self.functions:
if func["name"] == name:
return func
return None
def list_triggers(self) -> List[str]:
"""Return the list of trigger patterns for this SKILL."""
return self.frontmatter.get("triggers", [])
# Usage
with open("skill.md", "r") as f:
parser = SkillParser(f.read())
print(f"SKILL: {parser.frontmatter['name']} v{parser.frontmatter['version']}")
print(f"Triggers: {parser.list_triggers()}")
print(f"Functions: {[f['name'] for f in parser.functions]}")
print(f"Conversation state keys: {list(parser.conversation_state.keys())}")
This parser is intentionally minimal — it demonstrates the structure without adding complexity like full Markdown table parsing or response shape extraction. Production implementations would extend it to handle the full specification.
Design Principles Behind the Protocol
Three design constraints shaped the SKILL protocol's structure:
Constraint 1: Minimal token overhead. When an AI model processes a SKILL file during a conversation, it must do so with minimal latency. The specification avoids verbose prose and favors tabular formats that the model can parse with simple regex patterns. Each function definition targets under 500 tokens.
Constraint 2: Explicit over implicit. Rather than relying on the AI to infer how to handle a rate limit or format a date, every non-obvious behavior is documented explicitly. This trades verbosity for reliability — an AI that follows explicit instructions is more predictable than one that reasons from examples.
Constraint 3: State is externalized. The conversation state schema is not embedded in the AI's context memory. It is defined in the SKILL file so that the AI can read it at the start of each session and maintain consistent state across turns. This also enables debugging — you can inspect what the AI believes the current state to be.
Best Practices for SKILL Consumers
If you are building an AI agent that consumes TickDB's SKILL protocol:
Activate the SKILL only on relevant triggers. Do not route every market-related query through TickDB. The SKILL's trigger patterns exist to prevent unnecessary activation overhead. For example, "What is the weather in New York?" should not activate the market data SKILL even if the word "market" appears in the response.
Prefer state reuse over redundant calls. Before invoking get_kline, check whether you already have the data in last_response. Redundant API calls waste rate-limit budget and increase latency.
Surface errors in user-facing language. The error codes in the SKILL specification map to technical conditions. When reporting errors to end users, translate them into plain language. Code 3001 becomes "The data source is temporarily busy — please try again in a moment."
Pin the SKILL version. The version field in the frontmatter is your compatibility anchor. When you integrate the SKILL into a production agent, pin to a specific version. Newer versions may change function signatures or add breaking changes.
Closing
The SKILL protocol transforms TickDB from a data source that humans query into a data source that AI agents can reason about. By providing a structured, machine-readable contract — covering triggers, function definitions, response formatting, error recovery, and conversation state — the protocol ensures that AI assistants can interact with TickDB reliably without hallucinating parameters, mishandling errors, or making redundant calls.
Whether you are building a trading copilot, an automated research assistant, or a portfolio monitoring agent, the SKILL protocol gives your AI the context it needs to treat TickDB as a true capability rather than a black box.
Next Steps
If you're an AI developer building trading agents, explore the full skill.md specification and the TickDB SKILL integration guides in the documentation portal.
If you want to test the SKILL in your workflow: Sign up for a free API key at tickdb.ai and install the tickdb-market-data SKILL from your AI tool's marketplace.
If you need enterprise-grade rate limits and full historical OHLCV coverage, reach out to enterprise@tickdb.ai for Professional and Enterprise plans.
This article does not constitute investment advice. Markets involve risk; past performance does not guarantee future results.