Sessions ​
A MemoryScope connects one product conversation to its stored message history. Pass the same session ID, optional user ID, and optional JSON metadata to every agent run that belongs to the conversation.
1. Create one authorized session ​
const session = { sessionId: 'thread_123', userId: user.id, metadata: { tenantId: user.tenantId } }The session ID must be a non-empty string. Use a product conversation identifier, not a request ID, model call ID, browser connection, or temporary trace ID.
Reuse the same scope values for every operation that should address the same stored conversation.
2. Continue the conversation ​
let first = await supportAgent.generate({
prompt: 'Summarize my latest invoice.',
session,
});
while (first.type === 'interaction' && first.interaction.type === 'tool-approval') {
// Obtain the decision from the authenticated approver before resuming.
const decision = await requestApproval(first.interaction)
first = await supportAgent.resume(first.continuation, {
type: 'tool-approval',
approved: decision.approved,
reason: decision.reason,
})
}
if (first.type !== 'response') {
throw new Error(`Unexpected agent outcome: ${first.type}`);
}
const followUp = await supportAgent.generate({
prompt: 'When is it due?',
session,
});
if (followUp.type === 'response') {
console.log(followUp.output);
}Before each run, Anvia loads the stored messages and uses them as history. New runtime messages are appended according to the configured save policy.
The example handles tool approval before requiring a completed response or starting the follow-up. requestApproval is application code that waits for an authorized decision. Resume through the same parent agent; the continuation retains its memory context. Handle other interaction types according to the product flow.
3. Stream a session run ​
for await (const event of supportAgent.stream({
prompt: 'Draft a short invoice explanation.',
session,
})) {
if (event.type === 'text_delta') {
process.stdout.write(event.delta);
}
if (event.type === 'response' || event.type === 'interaction' || event.type === 'blocked') {
console.log(event.runId, event.usage);
}
}Scoped streams use the same history and save policy as generated responses. Closing an active stream cancels the run and triggers normal failure cleanup.
4. Inspect stored state ​
const messages = await memoryStore.load({ scope: session })load() returns the provider-neutral Message[] currently stored for the scope. A completed agent result exposes the latest run's optional contextUsage directly.
For React chat hydration, convert server-loaded memory with initialMessagesFromMemory() from @anvia/react. On the next request, send only the new user input through the server session; do not trust a browser transcript as the durable source of truth.
5. Clear a conversation ​
await memoryStore.clear({ scope: session })Use the store's clear() method for an authorized deletion request, retention cleanup, or isolated test setup. The adapter deletes the conversation addressed by the full storage scope.
Continue with Save policies.