Entry
Apeira stores everything as append-only entries. This page covers the entry model: the core entry types, how to build entries, custom entry types, and the storage contract.
AgentEntry
Every item stored by Apeira is an AgentEntry:
interface AgentEntry<T extends keyof AgentCustomEntry = keyof AgentCustomEntry> {
data: AgentCustomEntry[T]
id: string
parentId?: string
timestamp: number
type: T
}Every entry has:
id– a unique identifier (crypto.randomUUID()by default).type– the entry kind, e.g.'input','state','event'.data– the payload, typed bytype.timestamp– creation time in milliseconds. (Date.now()by default)parentId– optional pointer used by sessions and semantic entries to build trees.
Core entry types
input
input entries store messages, tool calls, and model outputs that are passed to the runner.
import { entry, toAgentInput, user } from '@apeira/core'
const e = entry('input', user('Hello.'))
const inputs = toAgentInput([e])See Input for the input types and helpers.
state
state entries store snapshots of agent.state. The latest state entry is restored on init().
import { entry } from '@apeira/core'
const e = entry('state', { userName: 'Alice' })See State for managing state.
event
event entries store events emitted with agent.emit(..., { save: true }). They are typically used for audit trails or session tracking.
import { entry } from '@apeira/core'
const e = entry('event', {
turnId: crypto.randomUUID(),
type: 'agent.reset',
})Helpers
entry(type, data)– creates anAgentEntrywith a generatedidandtimestamp.toAgentInput(entries)– filters an array of entries to onlyinputentries and returns their data.
import { entry, toAgentInput, user } from '@apeira/core'
const inputEntry = entry('input', user('Hello.'))
const inputs = toAgentInput([inputEntry])How Apeira uses entries
- Initialization – if storage has no
inputentries, Apeira writesinitialInput. - State restore – the latest
stateentry is loaded intoagent.state. - Turn start – Apeira reads entries, transforms them through plugins, and converts them to model input with
toAgentInput(). - Turn success – new inputs and model outputs are appended as
inputentries. - Reset – storage is cleared and
initialInput/initialStateare restored.
Custom entry types
Plugins can add custom entry types by extending AgentCustomEntry:
import type { AgentCustomEntry } from '@apeira/core'
declare module '@apeira/core' {
interface AgentCustomEntry {
'my-plugin/config': { value: string }
}
}After declaration, entry('my-plugin/config', { value: 'x' }) is fully typed. Custom entries are preserved by @apeira/session as ordinary semantic nodes.
Reading entries
You can read the current storage entries at any time:
import { createAgent, mem } from '@apeira/core'
import { responses } from '@apeira/core/responses'
const agent = createAgent({
instructions: 'You are a helpful assistant.',
runner: responses({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
}),
storage: mem(),
})
const entries = await agent.storage.read()Each entry has id, timestamp, type, and data. See Storage for choosing a storage backend.
Storage contract
AgentStorage only sees entries. It does not know about turns, plugins, or runners. This separation is what makes custom storage backends simple: they only need to implement append, clear, and read.
