Skip to main content
RQL lets your MCP client run one read-only SELECT over one project. Pass a project slug provided by the user or already resolved in the current organization. Use list_projects to discover projects or verify the selection when needed. You may also pass org when you have access to multiple organizations. The server restricts the query to that organization and project. Reach for RQL for aggregate questions: counts, GROUP BY breakdowns, trends, and comparisons across events, traces, users, and conversations. Keep the dedicated tools for text search, signal definitions, full events, conversation paging, and trace context. Your agent loads raindrop_skills with topic: "rql" for a compact guide with common event fields and an example query, and topic: "rql_reference" for the full table and function reference. RQL returns redacted content and does not restore original PII.

Query syntax

RQL supports SELECT, FROM, WHERE, GROUP BY, ORDER BY, LIMIT n BY, and LIMIT over one of five virtual tables: events, traces, users, user_days, or conversations. It supports the fields and functions in the RQL reference. Joins, unions, and window functions are not supported. Give computed expressions aliases that do not reuse source column names. users and conversations are lifetime and whole-conversation rollups; user_days is the same user rollup per UTC day. Without a day filter, time_range and its seven-day default bound day; a WHERE on day replaces that window, so it can read older days. Filtering by last_seen or end_ts selects recently active records; their event_count and message_count still cover the full lifetime or conversation. For event counts, use uniqExact(event_id). For span counts, use uniqExact(tuple(trace_id, span_id)). Recent reprojections can expose more than one physical row per logical record. Event errors and span errors are different populations. Aggregates of mutable fields can still reflect multiple versions. The one cross-table form is an identity subquery: event_id, convo_id, or user_id IN (SELECT <the same column> FROM <table> WHERE …). The inner query runs over the same project scope and time window as the outer query, may use GROUP BY and HAVING, and cannot nest another subquery. A statement may contain at most two identity subqueries, counting both IN (SELECT …) and NOT IN (SELECT …) across all clauses and expressions. RQL also supports a single-level FROM (SELECT …) AS name subquery. Its inner query reads one virtual table and inherits scope, time-window, dashboard-filter, exclusion, and hidden-signal options. The outer query can read only selected inner outputs. Name every computed inner output with AS; nested FROM subqueries and outer IN (SELECT …) are not supported. The equivalent single-CTE form is WITH name AS (SELECT …) SELECT … FROM name. WITH supports exactly one named subquery and the outer query must read that name. ARRAY JOIN array_expr AS item expands array elements into rows; LEFT ARRAY JOIN preserves rows for empty arrays. List multiple arrays in one clause with comma-separated expressions:
Aggregate functions support the -If, -Array, and -Distinct combinators, with at most two different suffixes on a valid aggregate (for example, sumArray, avgDistinct, and groupUniqArrayIf). Funnel aggregates operate on each group in timestamp order. windowFunnel returns the deepest condition reached inside a seconds window; retention returns a 0/1 array for condition retention; sequenceMatch tests a pattern and sequenceCount counts its non-overlapping matches. For example, the deepest step each user reached within an hour:
For example, the share of events whose trace ended in an exec error:

Time and cost limits

MCP enforces a window of at most seven days for events and traces. Pass optional time_range: {from, to} with ISO timestamps to choose a historical or narrower window. from is inclusive and to is exclusive. Omitting time_range selects the latest seven days. Choose 24 hours when the question gives no time range. The compiler applies this window independently of SQL filters. A timestamp predicate can narrow the window but cannot widen or move it. Set time_range when searching older data; changing only the SQL predicate can leave the query outside the selected window. The response’s timeRange reports the enforced bounds. Lifetime users and conversations rollups do not use this window. For example, this tool call counts events in a historical week:
Ranges wider than seven days are rejected. For a longer investigation, query successive windows. Keep the same explicit time_range when paging with LIMIT and OFFSET. Filters on ai_input or ai_output require a window of 24 hours or less, set by time_range or an ANDed timestamp filter; add a selective identity or event-name filter alongside them. LIMIT caps returned rows, not bytes scanned. MCP uses the shared RQL compiler; Triage retains its existing time-range behavior. The query text limit is 20,000 characters. Queries return 100 rows by default and at most 1,000 with an explicit LIMIT. Each query runs for at most 30 seconds. Narrow a query after a timeout or resource-limit error; do not retry it unchanged. Each organization can have 8 RQL queries running at once through MCP. A query that arrives while all 8 are busy waits up to 8 seconds for a slot, then fails with a retryable “too many RQL queries” error.

Examples

These examples use a timestamp predicate to narrow the enforced window to the last 24 hours. To query an older period, pass time_range instead. Replace chat_message with an event name from your project. Resolve signal names through list_signals before filtering by signal ID.

Count events by model

Count failed events and affected users

Trend of event volume

Discover property keys in recent events

Search a narrow set of inputs

Pass a time_range of at most 24 hours with this query.

LLM cost by model

Count failing spans

Read the result

The result includes columns, data, rowCount, applied limit flags, truncation flags, statistics, default-window information, and supported reference_targets. rowCount is the number of returned rows before clipping. It is not a count of all matching events. Treat a clipped result as incomplete and state its time range and limits in your answer. A syntax error returns a message and source span. Correct the indicated part of the query. If a query returns an event or trace ID that needs closer inspection, call get_event or get_trace for the full evidence. An empty result or failed lookup does not prove that the behavior never occurred. RQL cannot express regex signal definitions, signal properties, or recurrence rules; use the signal tools for those questions.