Knowledge Base
API referenceOpen app
KB-407Updated October 15, 2026

One engine, one door, every surface

Kernels, shredders, Enhance, arenas, seers, collections and Openers all work the same way: an endpoint with one configuration file, one call that runs it, a run row that records what it ran with, and a read-back that checks it.

Letterstory is built out of a small number of primitives: a writing kernel, a shredder, Enhance (the passes that add links, citations, visuals and metadata), an arena (research), a seer (a watcher), a collection (a publication that produces and publishes posts) and Openers (cold-email opening lines). Everything the product does is one of those seven, or an assembly of several. Each one is written up at /docs/primitives.

They are worth learning as a set, because they are deliberately the same shape. Once you have called one, you can call the others without reading much.

The seven

PrimitiveWhat one run doesThe callCapability
KernelA brief in, a finished article outrun_kernelkernel:write
ShredderA document in, the same document out with every sentence rewrittenrun_shredshredder:write
EnhanceA written post in, the same post with links, citations, visuals and metadatarun_enhance_passarticle:write
ArenaA topic in, a sourced and fact-checked outline outrun_arenaarena:write
SeerOne poll of a watched source, deduped and judgedrun_seerseer:write
CollectionOne whole post: sourced, written, enhanced, published, and the site rebuiltrun_collectioncollection:write
OpenersA prospect in, a hand-approved cold-email opening line outrun_ledelede:write

A collection run composes an arena, a kernel and the Enhance passes, which is why it takes the longest and why its own read-back quotes theirs.

The same five ideas, every time

1. An endpoint is the thing you call. A kernel endpoint, a shredder endpoint, an arena, a seer, a collection: each is a named row in your organization with its own public id, and that id is what appears in the URL (POST /api/kernel/ingest/{id}, /api/shred/ingest/{id}, /api/arena/ingest/{id}, /api/collection/ingest/{id}). Kernel endpoints, shredder endpoints and arenas are provisioned for you the first time you use one without naming it, so you never have to create an endpoint before your first call. Seers and collections you create yourself, because each one stands for a specific source or a specific publication.

2. Its configuration is one file. Not a scattering of settings across pages. get_*_config returns one document; set_*_config takes that same document back. What you read is exactly what you may write, so the workflow is read it, edit it, send it.

letterstory kernel endpoint config <id> > kernel.json
# edit kernel.json
letterstory kernel endpoint config <id> --file kernel.json

The endpoint files replace wholesale (a field you leave out is cleared). The collection file patches (a section you leave out is kept), because it is the configuration of a live publication rather than a call template.

3. A call sets constraints; a constraint beats a default. Everything you can set on an endpoint's defaults you can also set per call, and the call wins, field by field. So an endpoint is "how this pipeline usually runs" and a call is "except this time".

4. Every run records what it ran with. The run row carries constraints: the effective options after the defaults were merged in, as one document. "What did this run actually run with" is one read, not an investigation. Where a value could have been inherited from your organization's own settings, the row says which fields you declared and which it inherited.

5. Every run reads itself back. The run row also carries verification: a short list of checks, each pass, fail or skipped, that reads the constraints back against what came out. Each primitive's checks are listed at /docs/primitives. A collection run's checks quote the arena run's and the kernel run's own read-backs, so one read tells you which layer a bad post came from.

Two rules make verification worth reading. A check that did not apply is skipped, never quietly reported as a pass. And a failure is recorded and returned, never hidden, and never blocks: what to do about it is your pipeline's decision, not ours.

Who is billed: direct against internal

Every run is stamped with an origin.

  • direct: you asked this door. It counts against your balance.
  • internal: another part of Letterstory asked it on your behalf, because you told that product to run. Auto-Pen's research and writing, a collection's cadence, a phantom's launch. Recorded in your telemetry, billed to that product, not to you.

That is why a hosted post that researches, writes and shreds does not spend three separate balances, and why turning metering on for a primitive changed nothing for the pipelines already using it.

BalanceOn the houseSpent by
get_kernel_run_balance10 runsrun_kernel, the Kernel Studio
get_shred_balance10 shredsrun_shred, the Shredder Studio
get_arena_run_balance50 runsrun_arena, the Arenas Studio, the post's Research panel
get_seer_run_balance50 runsrun_seer, a dry run, the run-now button
get_lede_balance10 ledesrun_lede, matched runs only
get_phantom_balance3 sitesA hosted site being live, not its posts

Collections are the exception that proves the rule: a phantom is sold as a site that keeps running, so what is metered is sites live at once, and each site's throttle is its weekly cadence. A post you ask for spends that week's cadence budget and is refused past it, rather than spending a separate credit.

A run that errors is free, everywhere.

Every surface is the same function

The app, an agent over MCP, plain HTTP, and the CLI are four projections of one function with one schema. There is no capability the app has that an agent does not, and the argument names are the same everywhere:

SurfaceKernelShredderArenaCollection
MCPrun_kernelrun_shredrun_arenarun_collection
HTTP/api/kernel/ingest/…/api/shred/ingest/…/api/arena/ingest/…/api/collection/ingest/…
CLIkernel writeshredder runarena runcollection run
AppKernel StudioShredder StudioArenas StudioThe Control Room

This is enforced, not merely intended: the API reference at /docs is generated from the same manifest the tools are, and a build fails if the CLI stops sourcing a field a tool declares.

Long runs

Everything above except a short shred is submit-then-poll. Start it, keep the run id, poll it. See KB-405 for the pairs and how long each takes.

Documents

Anywhere you can hand Letterstory a document (a Studio, the CLI's --file, Strategy context, extract_document over MCP) the same list of formats is accepted: Markdown, plain text, Word, PDF, Rich Text, OpenDocument, HTML, CSV and TSV, and WebVTT or SubRip captions. Images embedded in a document are kept where the format lets us reach them, and where it does not, the refusal says so and names the export that would work instead of failing silently.

Related