Runlog docs

Start building

A plan buys a weekly allowance, sized for steady work.

Start

Actions

One route takes every action: POST https://runlog-7613480744.us-central1.run.app/v1/api/actions, the key as bearer, the project on X-Project-Id. Reads run at a Viewer key; writes need Editor. Every failure is one JSON object with an error string; 429 carries Retry-After.

The first call
curl -X POST "https://runlog-7613480744.us-central1.run.app/v1/api/actions" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{"action": "code_context_pack", "input": {"task": "what does this repository do?"}}'
Request in, response out
{"action": "code_context_pack", "input": { ... }}
{"action": "code_context_pack", "result": { ... }}
API key an rlka_ key, or an api-scoped rlk_ keySession the signed-in session; a key answers 401Site key a published site’s own key, in the bodyOpenAPI 3.0

Families carry three-part versions; a route or a version retires only on a published notice of at least 30 days. The retirement register renders under the Migration leg’s API versions lane.

artifact v1.0.0

project-write

Update an artifact

artifact_update: Generate or revise a structured artifact (report, memo, summary) built from the project's corpus.

FieldTypeRequiredDescription
artifactIdstringoptionalexisting artifact id to update; omit to generate a new one
purposestringrequiredwhat the artifact should produce

Contract Generation is detached: a dispatch returns the running task to poll, and a dispatch naming an artifactId is refused on the API surface today — omit it to generate a new artifact.

code v1.0.0

read

Pack code context

code_context_pack: Return the slice of an ingested repository one coding task needs: the declarations ranked most relevant to the task, each as a signature citing its file and line, packed to a token budget. Complements an exact-string search rather than replacing it — it answers which code to read, not what it says.

FieldTypeRequiredDescription
taskstringrequiredthe coding task in prose — what is being changed, in the words the codebase itself uses
seedSymbolsstringoptionaldeclarations already in your context, comma- or newline-separated; they steer the ranking and are never returned back to you
seedFilesstringoptionalfile paths already open in your context, comma- or newline-separated; same effect as seed symbols
budgetnumberoptionalapproximate token ceiling the pack fills. Leave it unset unless your context is genuinely smaller than the model window — unset fills to the model's own input window

Contract The response is signatures, never bodies: each declaration carries its header, file, and line span so you read the source yourself at the cited position.

Contract The pack is ranked for precision, not coverage — it returns the few declarations a task turns on and stops well short of the budget when nothing else scores. A short pack is an answer, not a truncation; re-dispatch with a sharper task rather than a larger budget.

Contract Seeds are subtracted from the answer: anything you name in seedSymbols or seedFiles steers the ranking and is never spent on your budget.

read

Find code units

code_references: List the ingested code units whose symbol name matches a typed prefix, each as an addressable reference — a stable symbol id, the symbol name as its label, and its file path as its sublabel. This is the manual override for retrieval: the named way to point at code.

FieldTypeRequiredDescription
querystringoptionalthe prefix typed so far; empty lists the first page alphabetically

Contract References are a bounded page ordered prefix-matches-first, then substring matches, each alphabetical, so the list stays stable as the user keeps typing.

Contract The symbol id is stable across re-ingests — store that, never the label, when persisting what a user picked.

document v1.0.0

project-write

Ingest a document

document_ingest: Pull a document into the project's corpus so its factions, cells, and entities feed the memory graph.

FieldTypeRequiredDescription
sourcestringrequireddocument url or file reference to ingest

Contract Dispatch only starts the ingestion: the source ingests on a detached task the response names, so poll that task rather than treating the dispatch as a completed ingest.

Contract One source, one page. Following links to the rest of a site is the research pass's job, so a whole site asked for here lands only what the named URL itself says.

read

Verify claims

document_verification: Extract the checkable claims from an ingested document and return a verdict ledger: per claim, whether the project's authority corpus SUPPORTS it (with the exact span), CONTRADICTS it (with the span), leaves it UNSUPPORTED (the corpus does not cover it — not a finding that it is false), or ABSTAINS when the evidence is too weak to call. Each row carries the exact locus it turned on. Scoped to the project the connection is bound to.

FieldTypeRequiredDescription
documentIdstringrequiredthe subject document to verify — the fileId ingestion handed back

Contract The ledger is three-valued, never two: UNSUPPORTED means the corpus does not cover the claim — a statement about coverage, not a finding that the claim is false — and is distinct from CONTRADICTED, which means the corpus asserts the opposite and carries the contradicting span.

Contract A verdict the evidence cannot support at the confidence threshold is ABSTAIN, never a forced call: a low-confidence resolve returns abstain rather than manufacturing a contradiction.

Contract Every SUPPORTED or CONTRADICTED row carries the exact locus it turned on — the faction and its SourceLocation anchor — so the cited span opens the precise place in the corpus. An UNSUPPORTED or ABSTAIN row cites nothing by design.

Contract The authority corpus is the project the connection is bound to, read as ground truth only — generated content is never cited as authority.

file v1.0.0

project-write

Upload a file

file_upload: Register a file the visitor already content-addressed and pushed to storage as chunks, staging it into the caller's session project so it ingests through the ordinary queue.

FieldTypeRequiredDescription
fileIdstringrequiredcontent-derived id of the whole file (43 base62 chars)
namestringrequiredthe file's display name
extstringoptionallowercased extension or mime subtype (e.g. txt, md, pdf)
fileTypestringoptionalmime content type stamped on the chunk blob
fileSizenumberoptionaltotal byte size of the file
filepathstringoptionalfolder the file lands in within the project — a client value; the server resolves the session project and overrides the destination, so a forged path lands in the session root
chunkIdsstring[]requiredordered chunk ids whose bytes reassemble the file
chunkingstringoptionalchunking mode: 'sections' | 'bytes' | '' for a single chunk

Contract The destination resolves server-side: the file always lands in the caller's session project, never in a project_id the visitor names.

Contract One session per caller: the first upload mints the session; later calls reuse it, each advancing its idle watermark.

Contract Upload URLs are minted by relay per chunk — a caller cannot name a source for relay to fetch.

memory v1.1.0

read

Query memory

memory_query: Read the project's Runlog memory. With a query, returns the cells, entities, and artifacts ranked relevant to it, each carrying its ids as provenance; without one, lists cells (units of knowledge) or entities as a windowed dump. Scoped to the project the connection is bound to.

FieldTypeRequiredDescription
kindstringoptionallist mode: what to read — 'cells' (default) or 'entities'
querystringoptionalnatural-language question or task; when present, results come ranked by relevance to it instead of as a paged dump
budgetnumberoptionalquery mode: approximate token ceiling the ranked response packs to. Leave it unset unless your context is genuinely smaller than the model window — unset returns every ranked row retrieval found, bounded only by the model's own input window
cursorstringoptionallist mode: the nextCursor from a prior dispatch, to continue the window
fileIdsstring[]optionalquery mode: tether the answer to these ingested files — only knowledge derived from them is returned. Use the fileIds ingestion handed back
entitiesstring[]optionalquery mode: tether the answer to these entity names — each one is seeded into the spine walk alongside the entities the query itself names. Use the entity names ingestion handed back
schemaobjectoptionalquery mode: a JSON Schema the answer must conform to. With it, the response carries a `structured` object matching the schema, grounded in the same retrieved rows; without it the response is the retrieved rows alone

Contract List reads are windowed: a dispatch returns one bounded page of items plus a nextCursor; pass the returned cursor to continue and treat an empty nextCursor as the final page — a single dispatch is never the whole memory.

Contract Query reads are budgeted, not paged: the response packs the most relevant cells, entities, and artifacts into the requested token budget and stops — dispatch again with a refined query rather than a cursor.

Contract A schema never replaces the query: the natural-language query is what decides WHICH knowledge is retrieved, and the schema only decides what SHAPE the answer takes over it. A dispatch carrying a schema and no query is refused rather than answered from an unranked corpus.

Contract Tethers constrain, they do not rank: a fileIds or entities tether narrows the answer to what those files and entities back, so a tether naming nothing the project holds returns an empty result rather than a broader one. Leave both absent to retrieve across the whole project.

Contract Every field of a structured answer is grounded in the returned cells — the rows stay on the response beside the structured object precisely so a caller can check each value against what it was derived from.

object v1.0.0

project-write

Submit a record

object_submit: Write one form submission as a typed record of the named-object type the site's owner bound to this action, validated against that type's declared fields.

FieldTypeRequiredDescription
dataobjectrequiredthe record's fields, keyed by the bound type's field keys
honeypotstringoptionalleave empty; a filled value marks the submission as spam

Contract The type is the owner's binding (the action's form wrapper), never a field of the submission: a payload that does not fit the bound type's declared fields is refused, not stored.

sku v1.0.0

project-write

Create a unit SKU

sku_create: Create a unit SKU row the storefront can sell: name, price, deliverable kind, scope, and turnaround. Price, scope and turnaround render from the catalog row at checkout time — never from page copy.

FieldTypeRequiredDescription
namestringrequiredthe SKU's display name
priceUsdnumberrequiredprice in USD
deliverableKindstringrequiredthe deliverable kind this SKU produces
summarystringoptionalone-line description of what the SKU delivers
scopestringoptionalthe scope of the deliverable
turnaroundDaysnumberoptionaldelivery turnaround in days

Contract The SKU id is server-generated from the name; a page never names a price it did not read from the catalog.

Contract The price, scope and turnaround render from the catalog row at checkout time, never from page copy.

Contract Intake answers ride the purchase into the delivery run; oversize intake is refused at mint, never truncated.

storefront v1.0.0

project-write

Create a storefront

storefront_create: Create a storefront host record bound to a project, so a published site has an identity tenant for visitor sign-up and a storefront for payments.

FieldTypeRequiredDescription
storefrontIdstringrequiredthe storefront identifier
projectIdstringrequiredthe project to bind the storefront to
namestringoptionalthe storefront display name

Contract The storefront is bound to one project; a project records the storefront it was created under.

Contract The storefront provides an identity tenant for visitor sign-up and a payment surface for unit SKUs.

unit v1.0.0

project-write

Buy one unit

unit_checkout: Mint one unit SKU's Stripe Checkout Session with the page's intake answers attached, for the visitor to pay on. Price, scope and turnaround come from the catalog row, never from the page.

FieldTypeRequiredDescription
skuIdstringrequiredthe catalog SKU id the visitor buys; off-catalog ids are refused
intakeobjectoptionalthe visitor's answers to the product's intake questions, keyed by question key; carried into the purchase and the delivery run
returnTostringrequiredwhere Stripe bounces the buyer afterwards; must be an allowed frontend origin

Contract The SKU id is the only thing the page names about the offer: the session's price, name and turnaround are read off the catalog row at mint, so a tampered id buys nothing.

Contract Intake answers ride the purchase into the delivery run; oversize intake is refused at mint, never truncated.