Skip to content
EvalBook

Datasets and examples

A dataset's schema, its working copy of examples with stable keys, splits, tags, metadata and review status, the rules every write obeys, and the SDK endpoints.

A dataset is a schema and a working copy of examples that curators add, correct, review and remove. Evaluations never run against the working copy: they run against an immutable version frozen from it (Versions and splits). This page is about the working copy and the rules it enforces whichever door an example comes in by.

Status (25 October 2026). The datasets component is implemented and its requirements EV-010 to EV-018 are marked implemented but unverified in the requirements ledger; verification is in progress.

Creating a dataset

Datasets → New dataset asks for a name, a description, a kind, a split policy, whether fields the schema does not declare are allowed, and whether the dataset is protected. The kind — text, structured, conversation, code, trajectory, document or mixed — starts the schema with default fields you can change on the Schema page. A protected dataset changes only through governed change sets (Protected data and governance).

The schema

A schema is a list of up to 200 fields, each with a role and a type:

  • roles: input (a key of the input object), expected (a key of the expected-output object), metadata (a scalar metadata key);
  • types: string, number, boolean, object, array, file, code_patch; metadata fields are string, number or boolean only;
  • constraints: required, minimum and maximum length or value, a pattern (a regular expression; one that nests repetitions is refused), allowed values, and for files a modality with its content types.

A role with no declared fields is unconstrained. A role with fields requires an object, and unknown keys are refused unless the dataset allows extra fields. Validation reports every problem with the field it is about; a row is rejected with diagnostics, never coerced or truncated. Saving the schema writes a new schema revision, and every version records which revision it was frozen under.

An example

Part Rules
stable_key 1–200 characters, immutable for the example's life; when omitted it is derived from the input's digest (k-…) so a re-sent row finds itself
input, expected JSON, validated against the schema; stored as canonical JSON with a sha256 digest, inline up to 256 KB and at Bookbag SSO's file store above that; at most 5 MB each
expected_origin none, human, source, observed_output or ai_suggested — where the expected output came from
split, family_key development, validation or holdout; examples sharing a family key stay in one split
tags, metadata up to 50 tags of 120 characters; up to 100 scalar metadata keys
attachments, repository_fixture up to 20 referenced files with declared modalities; a pinned repository, commit, patch and protected harness paths for code evaluations

Rules every door enforces

  • Exact dedup. Two live examples of one dataset never share an input digest (DUPLICATE_INPUT); a removed duplicate is offered for restoring instead.
  • Families stay together. Under the manual split policy an example whose family already lives in another split is refused (FAMILY_SPLIT_CONFLICT); under the hash policy the family is the hash basis, so it cannot straddle splits.
  • Keys are unique. A second example with an existing stable key is STABLE_KEY_TAKEN; an import or a batch may choose to update instead.
  • Limits are refused, never truncated.

Review status

Every example has a review status: pending, approved or rejected, with reopening back to pending. Only approved examples are frozen into a version. A curator's own data may be approved as it is written; anything curated, imported as candidates or generated arrives pending (Curation and synthetic data).

Correction history

Correcting an example keeps every previous value in its history, with the reason given (Why (kept with the history)). The example page's History tab lists each correction, newest first, with the value it replaced. Removing an example takes it out of the working copy; frozen versions keep it, its history stays, and it can be restored.

Who may do what

dataset.read opens structure, counts, digests, tags and provenance; example bodies — payloads, metadata values, history, diffs, candidates' content, exports — need dataset.read_body. Writing needs dataset.write, exporting dataset.export, and protected data dataset.protected.write. The dataset_curator role holds the first four; see Roles and access. Archiving a dataset needs its exact name, checked on the server; an archived dataset refuses writes until it is restored.

The SDK endpoints

With a project API key (Authorization: Bearer evb_…, scopes read and datasets:write), the tenant always the key's project:

GET  /api/v1/datasets                                   list
POST /api/v1/datasets                                   create (Idempotency-Key)
POST /api/v1/datasets/:id/examples                      insert or upsert up to 500 (Idempotency-Key)
GET  /api/v1/datasets/:id/versions                      list versions
POST /api/v1/datasets/:id/versions                      freeze (Idempotency-Key)
GET  /api/v1/datasets/:id/versions/:version/examples    frozen examples, pages of up to 500, with bodies

A batch is { "mode": "insert" | "upsert", "review_status": "approved" | "pending", "examples": [ … ] } and is validated whole: one invalid item refuses the batch with every item's problems by index, so a client never half-applies a batch it believes was rejected. upsert corrects an existing stable key with history kept and reports identical content as unchanged.