Agent analytics

SQL over what your agents did, on the copy they search.

Push traces, tool calls and events as documents, or import CSV, NDJSON and Parquet. Ask SQL with GROUP BY, exact counts and full-text predicates over REST or MCP. No warehouse to keep running: idle data costs only its bytes in S3.

9.3msClickBench hot geomean, 10M rows, through HTTP
0.6msCOUNT(*) over 10M rows, through HTTP
500krows/s, Parquet import
$0compute while nobody queries

One copy for search and SQL

The documents your agents search are the rows SQL counts. contains() and grep() in WHERE use the text index, so a needle in millions of log lines skips the blocks that can’t match.

Nothing to keep warm

Columns live in object storage next to the text. An idle analytics namespace costs only its bytes; the first query reads what it needs and the server’s cache keeps the rest close.

Bounded and metered

Each query has a time limit, a memory cap and a row cap, so a bad GROUP BY gets an error instead of taking a server down. Every answer reports its time, blocks scanned and object-store reads.

Log it, then ask

Each document’s metadata keys become typed columns; missing values are SQL NULL. The text stays searchable and filterable alongside.

events in
EV=https://api.skimmerdb.com/v1/namespaces/agent-events

# one document per tool call: the text is searchable, the metadata is columns
curl $EV/docs -H "Authorization: Bearer $KEY" -d '{"docs": [
  {"id": "run-981:3", "text": "TimeoutError: upstream took 30s (GET /v2/orders)",
   "meta": {"agent": "support-bot", "tool": "http_get", "ok": false,
            "ms": 30012, "tokens": 1840, "at": "2026-10-16 09:12:44"}}]}'

# or a whole export at once: CSV, NDJSON or Parquet, up to 2 GB a request
curl "$EV/import?format=parquet&id=call_id&text=error" \
  -H "Authorization: Bearer $KEY" --data-binary @tool_calls.parquet
questions out
# failures, latency and tokens per agent and tool
curl $EV/sql -H "Authorization: Bearer $KEY" -d @- <<'EOF'
{"sql": "SELECT agent, tool, COUNT(*) AS calls,
   SUM(CASE WHEN ok = 0 THEN 1 ELSE 0 END) AS failed,
   AVG(ms) AS avg_ms, MAX(ms) AS worst_ms, SUM(tokens) AS tokens
 FROM docs GROUP BY agent, tool ORDER BY calls DESC LIMIT 20"}
EOF

# the text index and SQL together: which tools time out, for whom
curl $EV/sql -H "Authorization: Bearer $KEY" -d @- <<'EOF'
{"sql": "SELECT agent, tool, COUNT(*) AS n FROM docs
 WHERE contains(text, 'timeout') AND ok = 0
 GROUP BY agent, tool ORDER BY n DESC"}
EOF

Measured

ClickBench’s 43 queries over its 10M-row web analytics table, imported through the API. Hot = best of runs 2–3.

ClickBench, 10M rowsResult
Hot geomean, 43 queries, through HTTP (auth, limits, metering, JSON)9.3 ms
clickhouse-local, same box, official MergeTree schema28.5 ms
COUNT(*) over 10M rows, through HTTP0.6 ms
First run of all 43 after import, namespace in S32.2 s in all
Answers vs the column engine run standalone33 of 43 identical; 10 differ only in tied rows
Import through the APIRows / s
Parquet, 10 × 1M rows (1.5 GB)488–512k rows/s
CSV with a schema, 10 × 1M rows (7.9 GB)436k rows/s, 343 MB/s
NDJSON, 1M rows (2.3 GB)175k rows/s, 408 MB/s

EC2 m7gd.2xlarge (8 vCPU, 32 GB), every engine on the same box one after another, 8 threads; ClickHouse 26.10 as clickhouse-local with the official schema. One benchmark on one machine, not a claim about every workload: broad filters and frequently changing dictionaries are still slower than ClickHouse and DuckDB in our comparisons, and SkimmerDB SQL has no joins yet.

Safe to hand to an agent

An agent with a read-only key can run SQL over its own runs through the sql_query MCP tool. Whatever it writes, the server stays up:

  • Time limit per query from the plan (10 s free, 30 s pro).
  • Memory caps on groups, distinct values and remote reads: past one, an error, not an outage.
  • Concurrency per tenant and per server; answers capped at 10,000 rows.
  • Isolation. Only FROM docs, the namespace the key may read.

What SQL covers today

SELECT … FROM docs with WHERE, GROUP BY, HAVING, ORDER BY, LIMIT/OFFSET; COUNT, COUNT(DISTINCT), SUM, AVG, MIN, MAX, CASE WHEN, COALESCE, LIKE, IN, IS NULL, DATE_TRUNC, REGEXP_REPLACE; contains(text, …) and grep(text, …); SHOW COLUMNS.

Not yet: joins, subqueries, window functions. They are next on the roadmap.

Questions

What is agent analytics?

Questions about what your agents did: which tools fail and how often, latency and token use per agent, which errors are new, how a change moved success rates. It needs fast aggregation over traces and events, and text search over their messages.

What SQL does SkimmerDB support?

One SELECT over a namespace’s documents (FROM docs) with WHERE, GROUP BY, HAVING, ORDER BY, LIMIT and OFFSET; COUNT, COUNT(DISTINCT), SUM, AVG, MIN, MAX, CASE WHEN, COALESCE, LIKE, IN, IS NULL, DATE_TRUNC and REGEXP_REPLACE, with SQL NULL semantics; plus contains() and grep() over the text. Joins, subqueries and window functions are not supported yet: they are on the roadmap.

How do I get data in?

Write documents as your agents run (each one’s metadata becomes columns, typed from the values), or import a file: CSV, NDJSON or Parquet, up to 2 GB and 1M rows a request, all visible together or not at all.

Is it faster than ClickHouse or DuckDB?

On ClickBench’s 43 queries over 10M rows, warm, on one 8-vCPU box, SkimmerDB through its HTTP API had a geometric mean of 9.3 ms against 28.5 ms for clickhouse-local. That is one benchmark, not every workload: in our own comparisons broad filters and frequently changing dictionaries are still slower than ClickHouse and DuckDB, and both have far wider SQL.

Can an agent query its own analytics?

Yes. The sql_query tool on the MCP server runs the same SQL. Give the agent a read-only key limited to its namespaces and it can check its own failure rates before choosing a tool.

What does a query cost?

A SQL query is metered as one query: $0.50 per million on pro, 100k a month free, plus object-store reads made by cold queries. Storage is $0.10 per GB-month.

Point your agents’ logs at it

Free up to 1 GB stored and 100k queries a month. No card to start.