ChangeGamer

← All guides · Selling to AI agents

Packaging a Corpus as a Product: Format, Schema, Versioning and Delivery

Part 9 of Selling to AI agents · 1,622 words · published 2026-08-04 · updated 2026-08-04 · Markdown variant

The packaging decisions behind selling a content corpus as a dataset product — export format, the free-sample/gated-full split, a per-record metadata schema, a corpus version number, and which of three delivery mechanisms to use — grounded in ChangeGamer's own three real export formats.

In short

  • A dataset product needs at least two export shapes, not one: a line-delimited record format for RAG/fine-tuning ingestion (NDJSON) and, if the buyer is meant to fine-tune directly, a chat-message format matching a training API's expected schema — a single flat text dump satisfies neither use case well.
  • The honest way to run a free sample next to a gated full export is field-level asymmetry, not a shorter file: ChangeGamer's free /api/corpus.jsonl nulls out premium record bodies and adds an access pointer object only to those null records, while the gated /api/corpus.full.jsonl always populates text and never carries an access field at all — the sample and the product are structurally different files, not the same file truncated.
  • A corpus version number and an MCP server version number answer different questions and should not be kept in lockstep: one tracks whether the content/schema changed, the other tracks the server manifest, and forcing them to match creates false-positive re-pull signals for a buyer who only cares about the first.
  • A per-record JSON Schema is what lets a buyer validate an export programmatically instead of reverse-engineering field shapes from a sample — ChangeGamer publishes one at /api/corpus.schema.json, derived live from the same source data it describes so the two cannot drift apart.
  • Pull endpoint, emailed file, and MCP tool are three delivery mechanisms with genuinely different latency and trust profiles, and a dataset seller should offer more than one rather than picking whichever is easiest to build first.

Part of the How to Sell to AI Agents: The Complete Guide to Machine Buyers guide.


Once a corpus has a license and a price, someone still has to decide what file format ships, how the free preview differs from the paid deliverable, how a buyer validates what they received, how version changes get signaled, and how the file reaches them. Those are packaging decisions, not legal or pricing ones — this article sits inside how to sell to AI agents, the pillar for this cluster, and covers the mechanics of shipping a corpus once the legal and pricing decisions are made elsewhere. It does not cover licensing terms (see licensing content for AI training) or tier-pricing design (see pricing tiers for machine buyers).

Pick a format for what the buyer will actually do with it

The right export format follows from the buyer's pipeline, not from whichever is easiest to generate, and one corpus product often needs more than one shape. ChangeGamer ships three:

Worth naming precisely because it is easy to get backwards: /api/finetune-sample.jsonl is always free and excludes every premium resource from all three task types — it is not a gated Corpus-tier deliverable, and it never becomes "the paid version" at any tier. It exists to demonstrate the corpus as training data using only what is already free, so a buyer can evaluate the shape of the paid product without a key.

The sample/full split is a field-level contract, not a shorter file

A free sample and a gated full export should have the identical record set and shape, differing only in which field values are populated — not a shorter file with fewer records. ChangeGamer's two NDJSON exports demonstrate the pattern exactly:

Field /api/corpus.jsonl (free sample) /api/corpus.full.jsonl (gated)
text null for premium records, full body for free records Always a populated string, for every record
access Present only on premium records (null-text ones) Never present, on any record
sources Present on every record, including premium/stubbed ones Present on every record
premium Present on every record Present on every record

The access object is the load-bearing detail: an inline pointer — reason, unlock_with_key, key_offer, checkout_url, offer_catalog, payment_manifest — so an agent hitting a null-text record knows exactly how to unlock it without a second discovery hop. sources (citation URLs from each resource's own "Verified sources" section) is deliberately populated on both files, even on stubbed premium records, because it is metadata about the resource, not paywalled content — a useful line for any seller deciding what belongs in a free sample: content is gated, metadata about the content generally is not.

A schema per record, published, not implied

A buyer should be able to validate a dataset export against a published schema instead of inferring field shapes from whatever sample they happen to have. ChangeGamer publishes /api/corpus.schema.json, a JSON Schema (draft 2020-12) covering both record types in its NDJSON exports: a meta record (always the first line — site, url, description, corpus_version, count, note, license) and a resource record (every subsequent line — record, url, slug, title, description, category, tags, updated, premium, text, plus the conditional access and always-present sources fields above). The schema's category enum is derived live from the actual resource data at build time rather than hand-maintained — a schema that can silently drift from the data it describes is worse than no schema, since it fails the one job (catching a malformed export) that justifies publishing it.

Versioning: one number for content, a different one for the server

A corpus needs its own version number, independent of any API-server or MCP-manifest version, because the two answer different questions for a buyer. ChangeGamer maintains CORPUS_VERSION as a manually-bumped semver string, currently 1.12.11: MAJOR for a breaking schema change (a stats or record field renamed or removed), MINOR for a resource added or removed, or a new additive field, PATCH for a content-only edit with no count change. That number is stamped into every corpus export's header and into /api/stats.json's corpus_version field, and is explicitly documented as something that must not track the MCP server manifest's own version field — the corpus number tracks content and schema, the server number tracks server-implementation changes, and conflating them would fire a buyer's re-pull check on changes unrelated to the data they licensed. If your dataset product and API server ship from one repository, resist giving them one version number: a buyer polling for freshness wants to know one thing, did the data change.

Freshness is a version comparison, not a file timestamp

Tell a buyer to compare corpus version numbers, not to eyeball a last-modified date, because a version bump is a deliberate signal and a file timestamp is not. ChangeGamer's per-record updated date is scoped narrowly — bumped only on a genuinely re-verified content delta, not a structural or formatting change — so it is a record-level signal, while corpus_version is the corpus-level one: every export header carries the version it was built from, and a keyed buyer compares that stamped number against the live value in /api/stats.json (also shown on the public /changelog page) to decide whether to re-pull.

What "re-pull" means also depends on which tier a buyer is on — a genuine point-in-time-versus-standing-subscription distinction, not a technicality. Per access and pricing for crawlers, ChangeGamer's one-time Corpus and Enterprise licenses deliver a snapshot — the license grant covers the version delivered at purchase, and getting anything shipped afterward means fetching /api/corpus.full.jsonl again with the same key. The annual Corpus Updates subscription instead re-sends the full corpus file at every renewal, always reflecting whatever is current at that date, with re-delivery performed manually by the operator rather than automatically. Choosing between a one-time license and a subscription is, in large part, choosing who is responsible for noticing a re-pull is due — the buyer, or the seller's own renewal process.

Three delivery mechanisms, three different tradeoffs

Offer more than one delivery mechanism: "pull," "push," and "agent-native tool call" solve for different combinations of latency and trust. ChangeGamer runs all three for the same corpus file, per access and pricing for crawlers:

None of the three replaces the others: the pull endpoint and the MCP tool serve an agent that already has a key and wants current data now; the emailed file serves the human on the other end of the purchase who wants a dated, addressable copy independent of key lifecycle. A seller who only builds whichever is easiest to implement is choosing a trust or latency profile by accident, not by design.

What this means for packaging your own corpus

Decide the export format from the buyer's pipeline first — NDJSON for streaming ingestion, a chat-format JSONL for fine-tuning, a full-text dump only for one-shot context loads — and ship more than one if buyers need more than one job done. If you run a free sample next to a paid full export, make the difference specific withheld field values on an identical record set, not a shorter file, with an actionable unlock pointer left in place of each withheld value. Publish a schema for the record shape, derived from live data so it cannot drift. Version corpus content independently from server or manifest version. And offer more than one delivery mechanism if your buyers mix machines that want to pull now with humans who want a dated, addressable copy.

Frequently asked questions

What format should I export a content corpus in for RAG or fine-tuning buyers?
Ship newline-delimited JSON (NDJSON) as the default, and add a chat-message JSONL export only if you specifically want to demonstrate or enable direct fine-tuning. ChangeGamer runs exactly this split: `/api/corpus.jsonl` and `/api/corpus.full.jsonl` are NDJSON, one JSON object per line, which streams straight into a vector store or a training job without a top-level array to parse; `/api/finetune-sample.jsonl` is a separate export in the `{"messages": [...]}` chat format that most fine-tuning APIs expect natively. A single full-text dump (all content concatenated into one document, ChangeGamer's pattern for that is `/llms-full.txt`, covered in [llms.txt vs. robots.txt vs. sitemap.xml](/articles/llms-txt-vs-robots-txt-vs-sitemap)) is fine for a one-shot context load but is the wrong shape for either streaming ingestion or fine-tuning.
How should a free sample of a corpus differ from the paid full version?
By withholding specific field values, not by shipping fewer records or a shorter file. ChangeGamer's free `/api/corpus.jsonl` includes every resource record, with free-resource bodies in full and premium-resource bodies set to `text: null` plus an `access` object naming exactly how to unlock that record. The paid `/api/corpus.full.jsonl` has the identical record count and shape, but `text` is always a populated string and the `access` field is absent entirely — a buyer's schema validator should reject a sample record whose `premium` is `true` and `text` is a non-null string, since that record came from the wrong endpoint.
Should a corpus version number match my MCP server's version number?
No — keep them independent. ChangeGamer's `CORPUS_VERSION` constant is a manually-bumped semver stamp for the content and schema of the corpus itself, explicitly documented in code as something that must not be kept in lockstep with the MCP server manifest's own `version` / `serverInfo.version` field, because the two track different things: one is "did the data or its shape change," the other is "did the server implementation change." A buyer polling your corpus version for a re-pull decision does not want that signal firing because you shipped an unrelated server update.
How does a buyer know when to re-pull a corpus they already licensed?
By comparing a version number, not a file date. ChangeGamer surfaces a live `corpus_version` field in `/api/stats.json` and on the public `/changelog` page; every corpus export (`/api/corpus.jsonl`, `/api/corpus.full.jsonl`) stamps the version it was built from in its own header record, so a keyed buyer can compare their held copy's version against the live one and re-pull only when it is higher. Annual-subscription buyers get this handled for them — the full corpus file is re-sent automatically at each renewal — while one-time-license buyers hold a point-in-time snapshot and must re-pull manually to get anything shipped after their purchase.

#corpus #packaging #ndjson #versioning #delivery #monetization #agents

Agents: this guide is available as Markdown and JSON; the whole cluster is indexed at /api/articles.json. The reference corpus behind it is at /llms.txt, with licensing at pricing.