Human-readable name for debugging and trace output.
slot
number
yes
Ordering slot (lower = recalled first). Use the Slot constants for well-known positions.
scope
MemoryScope
yes
Persistence boundary.
budget
BudgetConfig
no
Token budget allocation: a fixed number, a { min, max } range, or 'auto'.
hooks
MemoryHooks<TState>
yes
Lifecycle callbacks.
timeouts
Partial<LayerTimeouts>
no
Per-hook timeout overrides (ms).
onInitError
'throw' | 'disable'
no
What to do when init throws. 'throw' (default) surfaces the error and aborts the execution; 'disable' logs a diagnostic and runs the execution without this layer. Opt into 'disable' only for non-critical layers.
recallMode
'atomic' | 'eventual'
no
Whether recall() blocks the model call. 'atomic' (default) runs in the hot path; 'eventual' serves recall from cache and refreshes after store(), so the next turn sees the update. A harness configured with forceAtomicRecall treats every layer as atomic.
provides
LayerProvides
no
Typed data and function declarations exposed on ctx.memory['layerId']. Function entries are also auto-injected as LLM tools.
type BudgetConfig = | number | { min: number; max: number } | 'auto';
An omittedbudget behaves like 'auto': the layer has infinite headroom and splits the proportional pool with the other auto layers after finite layers take their share.
The runtime exports the Slot constant from @noetic-tools/core with these values; pass any of them as a layer's slot field to position it consistently with built-in layers.
recall may also return a bare string shorthand — the runtime wraps it in a developer message and estimates its token count — or null to contribute nothing this turn.
beforeToolCall / afterModelCall are the steering hooks: they return a SteeringDecision (allow / deny / guide) plus updated state. A deny surfaces as a NoeticError kind steering_denied.
onItemAppend runs when input items (user messages, tool outputs) are about to be appended — layers compose in slot order, each receiving the previous layer's output. It can transform, drop, or inject items, and may request a context re-render. Not called for LLM response items (use store).
projectHistory projects (caps, transforms) the history portion of the context window once per LLM step. Read-side only — itemLog storage is never mutated.
fs is the FsAdapter from ctx.harness.fs, giving memory layer hooks access to the same filesystem backend as tools and skill discovery (real, in-memory, or remote). shell is the corresponding ShellAdapter. callModel is the minimal model-call surface ({ model, items, instructions? }) — present only when the harness has an LLM provider configured, so LLM-backed layers must handle its absence. readLayerState snapshots a sibling layer's state by its layer.id.
In-memory layer-state store with centralized durable write-through. Every set() for a registered (execution, layer) pair is asynchronously mirrored to the layer's ScopedStorage — state written by provides functions, lifecycle hooks, or store() all persists the same way. Available from @noetic-tools/core/unstable.
Write state; mirrored durably when a target is registered (undefined deletes the durable key)
cleanup(executionId)
Drop all state and registrations for an execution
diagnostic(layerId, hook, error)
Sink for non-fatal layer errors (mirror failures report hook 'persist')
has(executionId, layerId)
Whether any state entry exists — distinguishes "init never ran" (no entry → init-bearing layer skipped) from "state explicitly cleared" (entry present → hooks keep running with undefined state)
registerDurable(executionId, layerId, target)
Register the durable write-through target for a layer (non-'execution' scopes; called by initLayers/spawnLayers)
flush(executionId)
Await all in-flight durable mirror writes
disable(executionId, layerId) / isDisabled(...)
Explicit disabled tracking for layers whose init failed with onInitError: 'disable'
Writes are coalesced per key (latest wins, one write in flight) and mirror failures never throw — they surface only through diagnostic.
A mapped type that collects each layer's provides declarations into a record keyed by layer id. Each key maps to the resolved data/function types declared by that layer.
Creates a LayerFunctionDecl that exposes a callable function on the memory object. execute returns { result, state? }; include state to persist an updated layer state.
function memory<const T extends readonly MemoryLayer[]>(layers: T): MemoryConfig<T>;
Collects an array of layers into a MemoryConfig with inferred _shape — e.g. memory([workingMemory(), planMemory()]). Pass the result to StepSpawn.memory or AgentConfig to get typed ctx.memory access.