Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: AI

AI

Embeddings and recordings

The full rules for ai.embed, ai.embed_all and recorded answers. The common case is under Asking for an embedding and Recorded answers.

  • embedding_dimensions: is a whole number from 1 to 16,000, pgvector's most, written out (ai.settings_invalid otherwise). Every ai.embed and ai.embed_all call needs it: an app that embeds without it is semantic.ai_dimensions_mismatch at the call's as:, as one whose type has another length is. The built-in driver doesn't send it, because a local model makes vectors of its own length and servers differ on the dimensions parameter. Instead, each vector the model answers with is read as V, so one of another length is misconfigured. A package whose provider can shorten its vectors sends it, through its mapping's embed:.
  • What ai.embed takes. The text is a value built on Text, or a Markdown, never one that may be none; embed_all takes a List of them (type.mismatch otherwise). as: is a type written out built on Vector with dimensions: (type.mismatch for a plain Vector, an Embedding or anything else). The options are model:, a name ai: { models: } gives (semantic.unknown_name), defaulting to embedding, which ai: must then name (ai.settings_invalid at the call), and timeout:, 1s to 10m, 5 seconds unless written. Any other is type.named_argument_unknown. Each of timed_out, over_budget and too_long needs an arm naming an unavailable failure, as ai.generate's conditions do. Only an action calls it.
  • The built-in driver sends OpenAI's embeddings request, POST <url>/embeddings with model and input, every text in one request, and reads data[i].embedding in index order. A 400 whose error.code is context_length_exceeded is too_long; no answer within timeout: is timed_out; the rest is read as ai.generate reads it (misconfigured, unavailable, sent again within timeout:). More than 100 texts in one embed_all is too_long, with nothing sent; no texts gives no vectors without asking. The call is logged and recorded as the operation embed of the model connection, and its answer reused on a rerun and kept as a step of a record, as ai.generate's is.
  • The fake's embedding of a text is dimensions numbers drawn from SHA-256 over the text's own SHA-256, the test's seed and a counter, each the top 24 bits of four bytes scaled to -1 to 1, then divided by the vector's length, so the same text under one seed always gives the same unit vector, and two texts give vectors far apart. fakes: { ai.embed: [...] } scripts only the three failures, each one call of ai.embed or ai.embed_all in the order made (ai.embed_all is scripted as ai.embed): a vector written out in a test would be as long as the model's, and embedding the same text gives the same vector anyway. A prompt called embed is scripted as the operation.
  • A recording is recordings/<prompt>/<name>.json in the prompt's own prompts/ folder: one JSON object with answer, a value of the type the prompt is asked for as written as json.write writes it, and version, the prompt's version it answered, answer_question@864ad76b. The answer keeps plain texts and numbers as placeholders naming their type, as a package's recordings do, so no personal data a prompt carried is committed; booleans, enum spellings, lists' lengths and null are kept as given. A placeholder is filled with a generated value of its type, at its place, each time the recording is read.
  • recorded("<name>") in fakes: { ai.<prompt>: } names one of the prompt's recordings, written out (semantic.fake_invalid with the nearest otherwise), and is one attempt answered with its answer, sent as the model sends one, so a strict mode's value wrapping and a Text answer's plain text are as a live answer's, and decoded by the call's own type.
  • Every recording is decoded by jadpo test, the build the gate runs. Each is a test of the recording kind, as a package's recordings are, named <prompt>'s <name> recording decodes, through each type an ai.generate call asks its prompt for as. A recording fails it as test.recording_undecodable when it doesn't decode, isn't one JSON object with an answer and a version, sits where no prompt of its folder's name is, or records a prompt no call asks.
  • A changed prompt's recordings are an alert, ▲ alert, on jadpo test's report, and in its --json as data.alerts (kind: recording_stale). The one hint after the footer points at jadpo ai show. Jadpo has no warning severity, and a stale recording still decodes, so neither check nor the run fails on it.

Markdown for agents: /docs/embeddings-and-recordings.md.Built from Jadpo main at a707efb.