Skip to content

Catalog

Build a pattern catalog from a local log file, paste, or glob, running entirely on the host without Kubernetes or a Log10x account. Returns each pattern's structural body with variable slots and the event count, plus optional PASS / FAIL assertions for minimum pattern count and required substrings.

Example

You

what's in /tmp/incident.log?

Log10x

1,403 events, 27 patterns. Top:

  1. Payment_Gateway_Timeout user_id={} took={}ms (412 events)
  2. GetCartAsync called with userId {} (218 events)
  3. Retry_Exhausted after {} attempts (174 events)

More to ask

  • "patterns in /var/log/app/*.log"
  • "verify that checkout logs and cart logs don't merge into one pattern"
  • "top 200 patterns in this corpus"

Prerequisites

A local Log10x engine: either the tenx CLI (install for macOS/Linux/Windows) installed locally, OR a local Docker container with the Docker daemon running (LOG10X_TENX_MODE=docker). When the mode is unset and Docker is running, Docker is auto-detected and preferred.

Schema and samples

Input example

Real call against the demo env (captured by scripts/capture-tool-envelopes.mjs).

{
  "source": "events",
  "events": [
    "2026-05-26 10:00:00 INFO payments-svc Transaction completed for user_42",
    "2026-05-26 10:00:01 INFO payments-svc Transaction completed for user_99"
  ],
  "top_n": 5,
  "view": "summary"
}
Input schema

Agent-facing JSON Schema (the canonical shape the MCP server publishes via tools/list):

{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "file",
        "events",
        "text"
      ],
      "description": "Input mode. `file`: read from a local path/glob. `events`: array of raw log lines. `text`: newline-separated log events as a single string."
    },
    "path": {
      "type": "string",
      "description": "Local file path or glob when source=file."
    },
    "events": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Inline log lines when source=events."
    },
    "text": {
      "type": "string",
      "description": "Raw text blob when source=text."
    },
    "top_n": {
      "type": "number",
      "minimum": 1,
      "maximum": 200,
      "default": 50,
      "description": "Max templates to return."
    },
    "expected": {
      "type": "object",
      "properties": {
        "min_templates": {
          "type": "number",
          "description": "Minimum number of distinct templates expected."
        },
        "required_patterns": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Substrings that must appear in at least one template body."
        },
        "forbidden_merges": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 2,
            "maxItems": 2
          },
          "description": "Pairs of substrings that must NOT appear in the same template body. Use to assert the templater never merges two structurally-distinct events into one identity."
        }
      },
      "additionalProperties": false,
      "description": "Optional assertions — turns extraction into validation. Each assertion reports pass/fail in the output."
    },
    "view": {
      "type": "string",
      "const": "summary",
      "default": "summary",
      "description": "summary returns the typed envelope (data.templates[], data.event_count, data.assertions, data.human_summary). The deprecated markdown view was removed; data.human_summary carries the prose distillation for chat rendering."
    }
  },
  "required": [
    "source"
  ],
  "additionalProperties": false
}

Source: src/tools/extract-templates.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):

2 events → 1 distinct template.

{
  "schema_version": "1.0",
  "schema_epoch": "2026-05-25",
  "tool": "log10x_extract_templates",
  "generated_at": "2026-05-26T15:37:44.398Z",
  "view": "summary",
  "summary": {
    "headline": "2 events → 1 distinct template."
  },
  "data": {
    "event_count": 2,
    "distinct_templates": 1,
    "shown_templates": 1,
    "cli_wall_time_ms": 7391,
    "cli_version": "10x engine v1.1.0, flavor: 'edge'\nNeed help? See https://doc.log10x.com",
    "templates": [
      {
        "rank": 1,
        "template_hash": "EBUOtrs^qq",
        "template": "$(yyyy-MM-dd HH:mm:ss) INFO payments-svc Transaction completed for user_$",
        "event_count": 2,
        "share_pct": 100
      }
    ]
  },
  "actions": [
    {
      "tool": "log10x_resolve_batch",
      "args": {
        "source": "events",
        "events": [
          "2026-05-26 10:00:00 INFO payments-svc Transaction completed for user_42",
          "2026-05-26 10:00:01 INFO payments-svc Transaction completed for user_99"
        ]
      },
      "reason": "richer per-pattern triage with variable concentrations on the same input"
    }
  ],
  "truncated": false,
  "warnings": []
}
Output schema

The data block inside the StructuredOutput envelope:

interface ToolData {
  event_count: number;
  distinct_templates: number;
  shown_templates: number;
  cli_wall_time_ms: number;
  cli_version: string;
  templates: Array<{
    rank: number;
    template_hash: string;
    template: string;
    event_count: number;
    share_pct: number;
  }>;
}

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).