Skip to main content

Query Model and Templates

This page defines the core EQL query object and copy/paste starters you can use before activation.

For the full trigger reference (conditions, indicators, operators, timeframes, and exact TA args schema), see Triggers, Signal, and TA Args Contract.

Intent Routing (Strict)

Choose source by intent before writing conditions:

IntentRequired sourceMinimum required fields
Account-anchored post intent (@user posts ...)source: "tweet"args.username (no @), args.text, args.minConfidence (baseline 80)
World event intent (ETF approval, exploit, sanctions, etc.)source: "news"args.text, args.minConfidence (baseline 80)
Fuzzy world-state predicate not naturally post/event matchingsource: "llm"method: "athena_condition", args.query, args.period (>= 1h)

When the prompt is account-anchored, do not route to news or llm first. Start with tweet.

Required API Sequence

For lifecycle operations in API key mode: validate -> create -> cancel (if active/recurring) -> delete (if terminal).

Trade actions (market_order, limit_order) must preflight GET /v2/auto/exchanges before create.

Inner Query Object (EQL)

The object below is the value of query. It is not the full HTTP request body by itself.

{
"conditions": { "AND": ["..."] },
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "..." }
}
],
"expiresIn": "24h"
}

HTTP Request Wrapper (Required)

When calling API endpoints, wrap the inner EQL object under a top-level query key.

Create request shape:

{
"query": {
"conditions": { "AND": ["..."] },
"actions": [{ "stepId": "step_1", "type": "notify", "params": { "message": "..." } }],
"expiresIn": "24h"
},
"title": "Optional title",
"description": "Optional description"
}

Validate request shape:

{
"query": {
"conditions": { "AND": ["..."] },
"actions": [{ "stepId": "step_1", "type": "notify", "params": { "message": "..." } }],
"expiresIn": "24h"
}
}

Allowed action types:

  • API key mode (/v2/auto/*): webhook, notify, telegram_bot, llm, market_order, limit_order
  • x402 mode (/x402/v2/auto/*): webhook, notify, telegram_bot, llm

Action params shape (key fields):

typeRequired paramsOptional params
notifymessage (1–1000 chars)
webhookurl (https only, allowlisted host)allNotifications (default false)
telegram_botbotToken, chatIdallNotifications (default false)
market_order / limit_orderexchange (hyperliquid or gmx), symbol, side, and exactly one of size / amount / positionSizePercent (+ price for limit)reduceOnly, leverage, tp, sl
llmaction (chat / summary / macro / accountAnalysis / tokenDiscovery / tokenAnalysis), callback.actionspeed (fast / expert), per-action extras

telegram_bot does not take a message field — the body is auto-composed from query title + description + trigger context. Use notify (in-app push) when you want to specify the message text yourself. allNotifications: true on webhook / telegram_bot opts the destination into lifecycle notifications (failed / expired / run-failed) in addition to trigger fires.

Trade-action prerequisite in API key mode:

  • market_order and limit_order require an active connected exchange. The required params.exchange selects the venue (hyperliquid or gmx), and a matching active connection must exist for that venue.
  • Without an exchange connection, trade actions fail at execution time when the trigger fires.
  • x402 does not support order execution actions.

Execution setup details: Trading Execution (API Key mode).

title and description are surfaced back inside delivered notifications (Telegram, webhook, notify). When a user suddenly receives an alert — often hours or days after setting it up — these fields are what let them recognize what fired and why they asked for it.

Without them, recipients get a condition summary with no context on the original intent, which hurts trust and slows follow-up.

Guidance:

  • title: short, human-readable summary of the trigger. Example: "BTC RSI oversold on 1h".
  • description: 1–2 sentences describing the thesis or intent. Example: "Mean-reversion entry: if BTC 1h RSI dips under 30 during US session, consider scaling in.".
  • Write them as if the recipient has forgotten they set this up — because they often have.

Expiry (expiresIn)

Allowed values: 1h, 2h, 4h, 8h, 12h, 24h, 2d, 3d, 5d, 7d.

Prefer 24h3d. Only use 5d or 7d for slow thesis watches.

Shorter expiries are better for three reasons:

  • Signal freshness. Crypto/market conditions change fast. A trigger set 7 days ago was based on a thesis that may no longer hold — narratives, sentiment, and fundamentals shift within hours, not weeks. Shorter windows force a re-evaluation: "do I still believe this setup?"
  • Noise and alert fatigue. The longer a condition sits open, the higher the chance it triggers on a random wick, a one-off news spike, or an unrelated move — not the signal you cared about. Short expiries keep the notification feed tied to current intent, not a graveyard of forgotten conditions.
  • Intent decay. If a setup hasn't played out in a few days, the original trade idea is usually invalidated anyway. A 7-day alert firing on day 6 rarely reflects what the trader would act on today. Most actionable setups resolve within 24–72 hours.

If /auto Doesn't Fit: Substitution Ladder

Before concluding your use case is out of scope, walk this ladder. Most intents resolve at rung 1 or 2.

  1. Rephrase through Builder Chat with a substitution instruction. Append "If anything is unsupported, return the closest supported query and list substitutions" to your chat prompt. Builder Chat will map your intent onto supported primitives rather than failing silently.
  2. Iterate on Validate Query. Validate Query returns structured errors (see Validation Errors → Next Action). Loop: validate → reshape → re-validate. Do not jump to "this isn't possible" after one rejection.
  3. Split into multiple queries joined by your runner. If a single condition tree can't express the logic (depth 3 / 10-leaf limits, or AND across incompatible sources), create 2+ queries and have your Agent Runner correlate their events.
  4. Use source: "llm" for fuzzy predicates. If the condition isn't a clean numeric rule, phrase it as a natural-language predicate evaluated by athena_condition. This covers narrative/sentiment/context questions that don't map to TA indicators.
  5. Pre-compute in your own service, use Auto as control plane. Only rung 5. If you have genuinely proprietary selection or signal logic, compute it yourself and feed the result into an Auto query — keep monitoring, lifecycle, and delivery inside Auto. See For Advanced Strategies.

Do not build your own monitoring/evaluation/trigger stack before walking rungs 1–4.

Anti-example: "I need to alert when BTC breaks a descending trendline"

A first instinct is "Auto doesn't compute trendlines, so I'll build this externally." Walk the ladder:

  • Rung 1: Rephrase as a supported proxy — "alert when BTC price crosses above its 4h upper Bollinger Band AND 1h RSI > 55". That's a supported query.
  • Rung 4: If the proxy isn't acceptable, use source: "llm" with a scheduled natural-language predicate — "has BTC broken its recent descending trendline on the 4h chart?".
  • Rung 5: Only if both fail: compute trendline-break externally, then feed a boolean into an Auto cron + llm query as the condition trigger.

Quick Action Snippets (for Builder Chat)

Use these snippets inside your POST /v2/auto/chat prompt so the generated query includes delivery wiring.

Webhook

Action requirements:
- action type: webhook
- deliver trigger payload to https://your-runner.example/auto/events
- keep payload concise and machine-readable

Telegram Bot

Action requirements:
- action type: telegram_bot
- params: botToken + chatId for my Telegram bot/chat
- include severity label in the query title/description so it lands in the auto-composed alert: info, warn, or high

LLM

Action requirements:
- action type: llm
- return one decision: long, short, or no-trade
- include 3 bullet rationale points and confidence score
- I will fetch full output via sessions APIs

Canonical Template: Daily Suggest + Trade (amount: "10")

Use this template for requests like: "suggest a BTC trade every 24h and execute with amount 10."

Required order:

  1. GET /v2/auto/exchanges (confirm hyperliquid active)
  2. POST /v2/auto/queries/validate
  3. POST /v2/auto/queries
{
"title": "Daily BTC suggest + trade 10",
"description": "Every 24h, generate a BTC suggestion and execute a 10-unit market order policy.",
"conditions": {
"AND": [
{
"source": "cron",
"method": "every",
"args": { "period": "24h" },
"operator": "==",
"value": true
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "llm",
"params": {
"objective": "Return one concise BTC trade suggestion (buy, sell, or no-trade) with confidence and rationale."
}
},
{
"stepId": "step_2",
"type": "market_order",
"params": {
"exchange": "hyperliquid",
"symbol": "BTC",
"side": "buy",
"amount": "10"
}
}
],
"expiresIn": "3d"
}

For HTTP calls, wrap conditions, actions, and expiresIn under top-level query.

Copy/Paste Query Templates

Use these as starting points with Validate Query before create.

Note:

  • Templates below are shown in a flattened shape for readability (title/description + conditions/actions/expiresIn).
  • For HTTP calls, convert them to API payload shape by moving conditions, actions, and expiresIn under top-level query.
  • action.params keys can vary by integration setup. Treat these as starter templates and adjust for your environment.

Signal Authoring Quality Rubric (X/Twitter Post + Event)

For Signal conditions (tweet.semantic, news.semantic), write args.text as a short factual claim.

Weak phrasing (bad)Actionable phrasing (good)
Bearish vibesOpens a short position on oil
Something bullishAnnounces a new stake in TSLA
Bullish on a coinPosts that they're bullish on $HYPE and $SOL
Market crashMajor DeFi protocol suffers a $200M exploit
War conflictUS imposes new sanctions on Russia
Big newsSEC approves a spot ETH ETF

Confidence guidance (minConfidence):

  • Baseline default: 80
  • Raise to 85-90 when you want fewer false positives
  • Lower to 70-75 when recall is more important than precision

1) Breakout Alert (Webhook)

{
"title": "BTC breakout above 100k",
"description": "Notify runner when BTC spot trades above the 100k round-number level.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "BTC" },
"operator": ">",
"value": 100000
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
}
],
"expiresIn": "24h"
}

2) Downside Guardrail (Telegram)

{
"title": "ETH downside guardrail (< 2500)",
"description": "Risk-off alert: flag if ETH breaks below 2500 so I can review exposure.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "ETH" },
"operator": "<",
"value": 2500
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "telegram_bot",
"params": { "botToken": "<TELEGRAM_BOT_TOKEN>", "chatId": "<TELEGRAM_CHAT_ID>" }
}
],
"expiresIn": "24h"
}

The notification body for telegram_bot is auto-composed from title + description + trigger context — there is no message param.

3) Runner Handoff (Webhook + Notify)

{
"title": "SOL breakout handoff to runner",
"description": "When SOL trades above 220, hand off to the agent runner and log a notify event.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "SOL" },
"operator": ">",
"value": 220
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
},
{
"stepId": "step_2",
"type": "notify",
"params": { "message": "SOL trigger fired; runner notified" }
}
],
"expiresIn": "24h"
}

4) Triggered LLM Analysis

{
"title": "BTC > 100k — LLM next-action review",
"description": "On BTC breakout, run an LLM pass to decide the next trading action under current conditions.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "BTC" },
"operator": ">",
"value": 100000
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "llm",
"params": { "objective": "Analyze trigger context and return next action" }
}
],
"expiresIn": "24h"
}

5) Multi-Symbol Confirmation

{
"title": "BTC + ETH joint breakout",
"description": "Confirm majors are moving together: BTC above 100k AND ETH above 3500 before acting.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "BTC" },
"operator": ">",
"value": 100000
},
{
"source": "price",
"method": "current",
"args": { "symbol": "ETH" },
"operator": ">",
"value": 3500
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "BTC and ETH confirmation trigger fired" }
}
],
"expiresIn": "24h"
}

6) Dynamic Comparison (Price crosses Bollinger Band)

Compare one live metric against another — no precomputation required.

{
"title": "ETH breakout above 4h upper BBand",
"description": "Dynamic comparison: fire when ETH price crosses above its own 4h upper Bollinger Band.",
"conditions": {
"AND": [
{
"source": "price",
"method": "current",
"args": { "symbol": "ETH" },
"operator": "crosses_above",
"value": {
"source": "ta",
"method": "bbands_upper",
"args": { "symbol": "ETH", "timeframe": "4h" }
}
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
}
],
"expiresIn": "48h"
}

7) Scheduled Check (cron)

Fire on a fixed schedule, no market condition required — useful for periodic LLM summaries or recurring portfolio sweeps.

{
"title": "Every 4h: portfolio sweep",
"description": "Recurring check every 4h to run a portfolio-context LLM pass.",
"conditions": {
"AND": [
{
"source": "cron",
"method": "every",
"args": { "period": "4h" },
"operator": "==",
"value": true
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "llm",
"params": { "objective": "Summarize BTC/ETH/SOL context and flag any risk shifts" }
}
],
"expiresIn": "3d"
}

8) LLM-Evaluated Condition (athena_condition)

Use when the predicate is fuzzy or narrative-driven and can't be expressed as a numeric rule.

{
"title": "Narrative shift watcher",
"description": "Fire when the dominant narrative around AI tokens materially shifts based on news + X context.",
"conditions": {
"AND": [
{
"source": "llm",
"method": "athena_condition",
"args": {
"query": "Has the dominant narrative around AI-sector tokens shifted materially in the last 6 hours based on news and X sentiment?",
"period": "1h"
},
"operator": "==",
"value": true
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "telegram_bot",
"params": { "botToken": "<TELEGRAM_BOT_TOKEN>", "chatId": "<TELEGRAM_CHAT_ID>" }
}
],
"expiresIn": "2d"
}

9) Signal Trigger: X/Twitter Post

Trigger when a specific monitored account posts something matching your description.

{
"title": "Binance Alpha listing post watcher",
"description": "Fire when cz_binance posts that Binance Alpha is listing a new token so I can review follow-through.",
"conditions": {
"AND": [
{
"source": "tweet",
"method": "semantic",
"args": {
"username": "cz_binance",
"text": "Binance Alpha is listing a new token",
"minConfidence": 80
},
"operator": "==",
"value": true
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
}
],
"expiresIn": "24h"
}

10) Signal Trigger: Event

Trigger when an event-style mention matches the semantic description.

{
"title": "ETH ETF approval event watcher",
"description": "Fire when event feeds indicate a spot ETH ETF approval so I can kick off a post-event playbook.",
"conditions": {
"AND": [
{
"source": "news",
"method": "semantic",
"args": {
"text": "SEC approves a spot ETH ETF",
"minConfidence": 80
},
"operator": "==",
"value": true
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Event trigger fired: spot ETH ETF approval signal" }
}
],
"expiresIn": "24h"
}

Poll Response Shape

GET /v2/auto/queries/{queryId} returns:

  • queryId (UUID)
  • status
  • credits (number, optional)
  • latestEvaluation
  • executions (array of execution objects, each with a UUID id)

Note: All query and execution identifiers are UUIDs (e.g., a12d20ff-6cb2-433e-afed-cc2e6a0380b6), not prefixed strings like q_123 or exec_123.

Common Agent Flows

Poll-Based LLM Flow

1. POST /v2/auto/queries                               -> create query with action.type = "llm"
2. GET /v2/auto/queries/{queryId} -> poll until execution with sessionId appears
3. GET /v2/auto/queries/{queryId}/sessions/{sessionId} -> fetch full analysis

Webhook-Based LLM Flow

1. POST /v2/auto/queries                               -> create with action.type = "llm" + callback webhook
2. Wait for webhook -> receive session reference / output
3. Optional GET session fetch -> /v2/auto/queries/{queryId}/sessions/{sessionId}