Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
elastic avatar

Evals Write Spec

  • 3 installs
  • 21.2k repo stars
  • Updated August 5, 2026
  • elastic/kibana

evals-write-spec skill documents Write LLM evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals Playwright fixture.

About

evals-write-spec skill documents Write LLM evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals Playwright fixture. Use when authoring new eval specs, adding datasets or evaluators, or debugging evaluation test failures.. name: evals-write-spec disable-model-invocation: true

  • Write LLM evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals Playwright fixture.
  • Platform-specific setup patterns for evals-write-spec.
  • Evidence-backed steps from upstream SKILL.md.
  • When-to-use criteria for evals-write-spec versus alternatives.

Evals Write Spec by the numbers

  • 3 all-time installs (skills.sh)
  • Ranked #1,759 of 2,203 Security skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

evals-write-spec capabilities & compatibility

Capabilities
evals write spec quick start · evals write spec when to use guidance · evals write spec integration patterns
Works with
elasticsearch
Use cases
security audit
From the docs

What evals-write-spec says it does

disable-model-invocation: true
SKILL.md
Eval specs use the `evaluate` Playwright fixture (not `test`). A spec file follows this structure:
SKILL.md
npx skills add https://github.com/elastic/kibana --skill evals-write-spec

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3
repo stars21.2k
Last updatedAugust 5, 2026
Repositoryelastic/kibana

How do I use evals-write-spec correctly?

Write LLM evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals Playwright fixture. Use when authoring new eval specs, adding datasets or evaluators, or debugging evaluation

Who is it for?

Teams implementing evals-write-spec workflows from the catalog.

Skip if: Skip when requirements clearly match a different specialized stack.

When should I use this skill?

User asks about evals-write-spec, write llm evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals .

What you get

Working evals-write-spec setup with validated configuration and next steps.

Files

SKILL.mdMarkdownGitHub ↗

Write Eval Specs

Spec File Anatomy

Eval specs use the evaluate Playwright fixture (not test). A spec file follows this structure:

import { evaluate, tags, selectEvaluators, type Example, type TaskOutput } from '@kbn/evals';

evaluate.describe('Suite name', { tag: tags.serverless.observability.complete }, () => {
  evaluate.beforeAll(async ({ fetch, log }) => {
    // one-time setup: install docs, create agents, load archives
  });

  evaluate.afterAll(async ({ fetch, log }) => {
    // teardown: uninstall docs, delete agents, unload archives
  });

  evaluate('test name', async ({ executorClient, connector }) => {
    await executorClient.runExperiment(
      { dataset, task },
      evaluators
    );
  });
});

When a suite has a custom src/evaluate.ts, import from there instead of @kbn/evals:

import { evaluate } from '../src/evaluate';

Tags

Every evaluate.describe must have a tag. Common choices:

TagWhen to use
tags.serverless.observability.completeObservability domain evals
tags.serverless.security.completeSecurity domain evals
tags.serverless.searchSearch domain evals
tags.stateful.classicStateful-only evals

Import tags from @kbn/scout or @kbn/evals (re-exported).

Datasets

A dataset is an array of examples with typed input, output (expected), and optional metadata:

type MyExample = Example<
  { question: string },
  { expectedAnswer: string },
  { tags?: string[] }
>;

const dataset = {
  name: 'my-dataset',
  description: 'What this dataset tests',
  examples: [
    {
      input: { question: 'What is 2+2?' },
      output: { expectedAnswer: '4' },
      metadata: { tags: ['math'] },
    },
  ],
};

Keep datasets focused. For local iteration, use --grep to run a subset:

node scripts/evals start --grep "my test name"

Tasks

The task function receives an example and returns the output to evaluate:

task: async ({ input }) => {
  const result = await someKibanaApi(input.question);
  return { answer: result.content };
}

Tasks can use any fixture available in the evaluate callback: fetch, inferenceClient, connector, esClient, kbnClient, or custom fixtures like chatClient.

Evaluators

There are two ways to provide evaluators to runExperiment:

1. Inline array -- pass evaluator objects directly (simple suites) 2. `selectEvaluators` -- typed wrapper that enforces Example/TaskOutput generics

CODE Evaluators

Deterministic, no LLM call. Use for binary checks:

{
  name: 'NonEmpty',
  kind: 'CODE',
  evaluate: async ({ output }) => ({
    score: output?.documents?.length > 0 ? 1 : 0,
  }),
}

LLM-as-Judge Criteria

Use evaluators.criteria(criteriaArray) for subjective quality checks. The judge LLM scores each criterion:

evaluators.criteria([
  'The response correctly identifies the top users.',
  'The response includes risk scores.',
]).evaluate({ input, output, expected, metadata })

Correctness Analysis

Compares output against expected answer:

evaluators.correctnessAnalysis().evaluate({ input, output, expected, metadata })

Groundedness Analysis

Checks if output is grounded in provided context:

evaluators.groundednessAnalysis().evaluate({ input, output, expected, metadata })

Trace-Based Evaluators

Available from evaluators.traceBasedEvaluators:

  • inputTokens, outputTokens, cachedTokens -- token usage
  • toolCalls -- number of tool calls
  • latency -- span latency in seconds

These read from the tracing ES cluster and require EDOT to be running.

RAG Evaluators

For retrieval-augmented generation with ground truth:

import { createPrecisionAtKEvaluator, createRecallAtKEvaluator, createF1AtKEvaluator } from '@kbn/evals';

See evaluator-patterns.md for full examples.

Available Fixtures

FixtureScopeDescription
executorClientworkerRuns experiments, exports scores to ES
inferenceClientworkerInference REST client bound to connector
connectorworkerThe model connector being evaluated
evaluationConnectorworkerThe judge connector
evaluatorsworkerDefaultEvaluators (criteria, correctness, groundedness, trace-based)
fetchworkerHttpHandler for Kibana API calls
esClientworkerElasticsearch client (Scout cluster)
kbnClientworkerKibana client with retries
traceEsClientworkerES client for trace queries
evaluationsEsClientworkerES client for evaluation score storage
logworkerToolingLog for structured logging
repetitionsworkerNumber of experiment repetitions
configworkerScout server config (hosts, auth)

The evaluateDataset Pattern

For suites with many specs that share the same task + evaluator wiring, extract a reusable helper:

`src/evaluate_dataset.ts`:

import type { DefaultEvaluators, EvalsExecutorClient } from '@kbn/evals';
import type { MyChatClient } from './chat_client';

export type EvaluateDataset = (opts: {
  dataset: { name: string; description: string; examples: MyExample[] };
}) => Promise<void>;

export function createEvaluateDataset({
  chatClient, evaluators, executorClient,
}: {
  chatClient: MyChatClient;
  evaluators: DefaultEvaluators;
  executorClient: EvalsExecutorClient;
}): EvaluateDataset {
  return async ({ dataset }) => {
    await executorClient.runExperiment(
      {
        dataset,
        task: async ({ input }) => {
          const response = await chatClient.converse({ messages: [{ message: input.question }] });
          return { messages: response.messages, steps: response.steps };
        },
      },
      [myCriteriaEvaluator, myToolCallsEvaluator]
    );
  };
}

In the spec:

import { evaluate as base } from '../src/evaluate';
import type { EvaluateDataset } from '../src/evaluate_dataset';
import { createEvaluateDataset } from '../src/evaluate_dataset';

const evaluate = base.extend<{ evaluateDataset: EvaluateDataset }, {}>({
  evaluateDataset: [
    ({ chatClient, evaluators, executorClient }, use) => {
      use(createEvaluateDataset({ chatClient, evaluators, executorClient }));
    },
    { scope: 'test' },
  ],
});

evaluate.describe('My suite', { tag: tags.serverless.search }, () => {
  evaluate('my test', async ({ evaluateDataset }) => {
    await evaluateDataset({ dataset: { name: '...', description: '...', examples: [...] } });
  });
});

Setup and Teardown

Use evaluate.beforeAll / evaluate.afterAll for expensive one-time operations:

  • Install product docs: POST to /internal/product_doc_base/install
  • Create agents/rules: Use fetch or kbnClient
  • Load ES archives: Use esArchiver.load(archivePath) (requires custom fixture)

Always clean up in afterAll -- delete agents, uninstall docs, unload archives.

Running Locally

# Full interactive flow
node scripts/evals start

# Specify model and judge
node scripts/evals start --model <connector-id> --judge <connector-id>

# Filter to a specific test
node scripts/evals start --grep "my test name"

# Run directly (services already running)
node scripts/evals run --model <connector-id> --judge <connector-id>

Common Mistakes

  • Forgetting the tag on evaluate.describe -- Scout validates tags at runtime.
  • Missing afterAll cleanup -- leftover agents/docs pollute subsequent runs.
  • Overly large datasets for local iteration -- use --grep to target a single evaluate() block.
  • Importing evaluate from @kbn/evals when the suite has a custom src/evaluate.ts -- you'll miss custom fixtures.
  • Using test instead of evaluate -- the evaluate fixture provides all the evals-specific wiring.

References

  • Evaluator type examples with real code: references/evaluator-patterns.md
  • Suite scaffolding: use the evals-create-suite skill

Related skills

FAQ

What does evals-write-spec do?

evals-write-spec skill documents Write LLM evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals Playwright fixture.

When should I use evals-write-spec?

User asks about evals-write-spec, write llm evaluation spec files with datasets, tasks, and evaluators using the @kbn/evals .

Is this skill safe to install?

Review the Security Audits panel on this page before installing in production.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.