Series
Build a time series over the offloaded cohort in the customer-owned S3 overflow bucket, over any window, with optional group-by on a label. The cohort is the events the Receiver diverted out of the SIEM; the Retriever reads them byte-range-scoped from the bucket in place. Returns counts per bucket; mode auto-selects between exact counts (small queries) and sampled estimates (high-volume or long-window). When sampled, series shape and top-value ranking stay reliable; individual bucket counts become approximate.
Example
You
hourly series of offloaded Payment_Retry, last 30d, by tenant
Log10x
720 hourly buckets over the offloaded cohort, broken down by tenant. The window holds ~8B events, too many to count exactly, so per-bucket numbers are sampled estimates. Series shape and the tenant ranking are reliable.
Top tenants: acme-corp 41% · globex 28% · initech 18% · umbrella 13%.
More to ask
- "force exact counts on a 6h window of
Auth_Failed" - "hourly
Retry_Exhaustedlast 7d, by service" - "sampled at 200 events per sub-window, last week"
Prerequisites
This tool requires the Retriever deployed. The Reporter is optional; without it, mode selection falls back to a window-length heuristic.
Schema and samples
Input example
Real call against the demo env (captured by scripts/capture-tool-envelopes.mjs).
Input schema
Agent-facing JSON Schema (the canonical shape the MCP server publishes via tools/list):
{
"type": "object",
"properties": {
"pattern": {
"type": "string",
"description": "Reporter-named pattern (Symbol Message). Auto-translated to `tenx_user_pattern == \"<name>\"` Bloom-filter expression. Use this when the agent has a pattern name from event_lookup / top_patterns / cost_drivers. Mutually exclusive with `search`; `search` wins if both provided."
},
"search": {
"type": "string",
"description": "Bloom-filter search expression using the TenX subset. Tightly bound queries (e.g., `tenx_user_pattern == \"PaymentRetry\"`) get the cheapest fetch path. Pattern-bound expressions are also what unlocks the Reporter-driven cost heuristic — without one, mode selection falls back to window-length only. Pass `pattern` instead for the common case of scoping to one Reporter-named pattern."
},
"from": {
"type": "string",
"description": "Start of the query window. ISO8601, epoch millis, or relative (`now-1h`, `now-7d`, `now-30d`)."
},
"to": {
"type": "string",
"default": "now",
"description": "End of the query window. Same grammar as `from`. Default `now`."
},
"filters": {
"type": "array",
"items": {
"type": "string"
},
"description": "In-memory JS filters applied after the Bloom-scoped fetch (AND-combined)."
},
"target": {
"type": "string",
"description": "Target app prefix. Defaults to __SAVE_LOG10X_RETRIEVER_TARGET__."
},
"bucket_size": {
"type": "string",
"default": "5m",
"description": "Time bucket granularity (`1m`, `5m`, `1h`, `1d`). Determines the resolution of the output series."
},
"group_by": {
"type": "string",
"description": "Optional enrichment field to group the series by — e.g., `tenx_user_service`, `severity_level`, `k8s_namespace`. Top-1000 group values are retained; tail collapsed to `_other_`."
},
"fidelity": {
"type": "string",
"default": "auto",
"description": "`auto` (tool decides via Reporter volume + window length), `full` (force exact aggregation — may exceed Lambda budget), `per_window_sampled` (force sampling, default K=1000 per sub-window), or `per_window_sampled:K` (custom K)."
},
"environment": {
"type": "string",
"description": "Environment nickname — required if multi-env."
},
"view": {
"type": "string",
"const": "summary",
"default": "summary",
"description": "summary returns the typed envelope (data.mode, data.bucket_seconds, data.series_count, data.points_returned, data.top_groups, data.caveats, data.human_summary). The deprecated markdown view was removed; data.human_summary carries the prose distillation for chat rendering."
}
},
"required": [
"from"
],
"additionalProperties": false
}
Source: src/tools/retriever-series.ts.
Output example
Real envelope from the demo env. view: "summary" returns the full StructuredOutput with typed data. Long arrays + base64 PNG bodies trimmed for readability; the real call returns them in full.
Headline (the 1-line agent-facing answer):
log10x_retriever_seriesran but its retriever precondition is not configured.
When the Retriever is not wired up, the tool returns a typed not_configured envelope. The remediation points at the Retriever (rq-1), standing up the S3 overflow bucket plus index, not the metrics backend, since this tool reads the offloaded cohort rather than a TSDB.
{
"schema_version": "1.0",
"schema_epoch": "2026-05-25",
"tool": "log10x_retriever_series",
"generated_at": "2026-05-26T15:38:35.780Z",
"view": "summary",
"summary": {
"headline": "`log10x_retriever_series` ran but its retriever precondition is not configured. This is an expected state, not a failure: read data.payload.remediation, surface the fix, and continue the chain without this tool."
},
"data": {
"status": "not_configured",
"precondition": "retriever",
"remediation": "## Retriever not configured\n\n..."
},
"actions": [
{
"tool": "log10x_advise_retriever",
"args": {},
"reason": "stand up the Retriever S3 archive + index, then re-run",
"role": "required-next"
}
],
"truncated": false,
"warnings": []
}
Output schema
The data block inside the StructuredOutput envelope. On a successful run:
interface ToolData {
status: 'success' | 'no_signal' | 'refused';
ok: boolean;
mode: 'full' | 'per_window_sampled';
from: string;
to: string;
window_ms: number;
group_by?: string;
actual_events: number;
points_returned: number;
series_count: number;
top_groups: Array<{ group: string; count: number }>;
wall_time_ms: number;
human_summary: string;
}
When the Retriever is not configured, data instead carries { status: 'not_configured', precondition: 'retriever', remediation } (see the output example above).
Envelope-level fields the agent should also read: summary.headline (1-line answer), actions[] (next-call chain hints as {tool, args, reason}), truncated: boolean, images[] (PNG attachments where applicable), schema_epoch (engine-ID stability boundary).