Skip to content

Serving a boot prompt

When a worker binds, a chatbot chat starts or a headless run begins, the platform picks one compiled boot prompt to give it. The three surfaces use the same rule and refuse in the same way. The platform also writes an immutable record of what it gave, so you can answer "which prompt was this session started with?" afterwards.

For the pointers that choose the prompt, see Boot-prompt pointers. For how a compiled prompt is produced, see Compile a boot prompt.

Status: the serving rule, the refusals and the record are merged on hadron-server (issue #2047). This page is written from that merged code and the GraphQL schema, not from a run. Serving is controlled by the deployment switch BOOT_PROMPT_SERVE_ENABLED (true turns it on; off by default). It has been switched on in the production deployment at hadronmemory.com since 2026-10-28; a deployment that leaves it off behaves differently. While it is off, nothing described here happens: the old prompt fields keep working, no refusal is returned and every record field reads empty. This page was not checked by a run against production.

Which prompt is served

The platform looks at three pointers, highest first, and the first one that is set decides. A lower pointer is never appended, and a set pointer whose node is deleted is refused rather than skipped (see BOOT_PROMPT_TARGET_DELETED).

Order Pointer Applies to
1 Worker a bind
2 Installed Agent (one App) a bind, a chat or a run in that App
3 Agent a bind, a chat or a run

A chat and a headless run have no worker, so they use level 2 or 3 only; a run cannot currently name a worker. A chat held in a memory that no App owns has no install level, so it is served the Agent's pointer only.

What is served is the compiled node's newest approved revision, exactly as it was approved. A newer edit that has not been approved is not served, and it does not cause a refusal. Only the compiled node is checked; the parts it was compiled from are not checked again at serve time.

Platform variables in the compiled text are filled when it is served, from what the surface knows (a bind knows its worker; a chat knows only its Agent). The values used are stored in the record.

A worker's open session finishes under the revision it was bound with. A recompile approved mid-session reaches the next bind, not the current one.

The five refusals

A refusal is a GraphQL error whose extensions.code is one of the codes below. extensions also carries surface (bind, chat or run) and agentName. It deliberately carries no node id, loc, revision or pointer, so an end user's chat refusal discloses nothing about the compiled node.

Code Meaning What to do
BOOT_PROMPT_NOT_SET No pointer is set at any of the three levels. Compile a prompt (it sets the pointer by default) or set a pointer.
BOOT_PROMPT_TARGET_DELETED The pointer that decides names a deleted node. The platform does not fall through to a lower, live pointer. Point the same level at a live node, or clear it so the next level decides.
BOOT_PROMPT_NOT_APPROVED The compiled node has no approved revision. The Agent's or App's manager approves it, as themselves and never through a worker session.
BOOT_PROMPT_NOT_SIGNED The serving App's organisation requires a signed prompt and the revision has none. Not reachable today: the organisation switch that requires signing does not exist yet, so nothing is refused as unsigned. Not applicable yet.
BOOT_PROMPT_RECORDED_REVISION_DELETED An open session was given a revision that has since been deleted. It is final: the session is not moved to newer text. Rebind.

An Agent with no servable prompt cannot be bound, chatted with or run. The refusal is the same on all three surfaces.

An open session whose bind began before serving was enabled has no record. It is never silently upgraded to the current revision: it reads no prompt and a typed notice until it rebinds.

The served-prompt record

Each bind, chat and run records what it was given. A record is immutable platform data: it cannot be edited and is never exported. It names revisions by id, revision number and hash. It never holds a loc, a title, a node or any prompt text, so reading a record hands you none of the included parts.

Field Meaning
kind BIND, CHAT or RUN
pointerLevel WORKER, APP_AGENT or AGENT: the level that decided
compiledNodeId the compiled node that was served
servedRevSeq the revision of that node that was served
provenanceRevSeq the compile revision that owns the provenance
compiledContentHash hash of the compiled revision as stored, before platform variables are filled; not of the final delivered text
ordinal 1 for a bind or a run; a chat counts up each time its served revision changes
variables the values the platform variables were filled with
servedAt when it was served
pruned true once the served revision is no longer retained
provenance(limit, offset) the revisions the compiled text was built from: nodeId, revSeq, hash and a per-entry pruned. Default page 50, maximum 200.

When records are written. A bind records once. A chatbot chat records at its start and again whenever the served revision changes. A headless run records once; the derived blocks it saw are in the run's progress, not in this record.

Where to read it

Surface Field Who may read it
A worker's open session Worker.servedPrompt whoever may read the worker's internals
A bind's records Session.servedPrompts(limit, offset) whoever may read the worker's internals
A run AppRun.servedPrompt whoever may read the run
A chatbot chat Chat.servedPrompts(limit, offset) whoever manages the App the chat runs in; never the chat's end user

A caller who may not read gets an empty page or null, never FORBIDDEN, so the record cannot be used to find out whether a prompt exists. Lists are pages of { items, total }, default 50, maximum 200. A chat held in a memory that no App owns is recorded under no App; until that is decided, only a platform admin (never an impersonation) can read it.