Skip to content

ConversationStore Interface

ConversationStore is the abstract interface for persisting multi-turn chat history. It is a runtime store (read on every agent turn) that is distinct from the TraceStore (fire-and-forget observability writes).

Import

import {
  ConversationStore,
  ConversationFilter,
  MessageQueryOptions,
  Conversation,
  ConversationMessage,
  ConversationRole,
} from "@modernpath/agent-framework";

ConversationStore Methods

Write Path

Method Signature Description
createConversation createConversation(conv: Omit<Conversation, "messageCount">): Promise<void> Creates a new conversation. The messageCount is initialized to 0 internally.
addMessage addMessage(conversationId: string, msg: ConversationMessage): Promise<void> Appends a message to an existing conversation. Updates conversation.updatedAt and increments messageCount. Throws if the conversation does not exist.
updateConversation updateConversation(conversationId: string, updates: Partial<Pick<Conversation, "title" \| "metadata">>): Promise<void> Updates conversation metadata such as title or the metadata bag.

Read Path

Method Signature Description
getConversation getConversation(conversationId: string): Promise<Conversation \| null> Retrieves a conversation by ID (without messages). Returns null if not found.
getMessages getMessages(conversationId: string, opts?: MessageQueryOptions): Promise<ConversationMessage[]> Gets messages for a conversation, ordered by timestamp ascending. Supports limit (returns most recent N) and before (pagination).
listConversations listConversations(filter: ConversationFilter): Promise<Conversation[]> Lists conversations matching the filter, ordered by updatedAt descending.

Lifecycle

Method Signature Description
deleteConversation deleteConversation(conversationId: string): Promise<void> Deletes a conversation and all its messages.

Types

Conversation

interface Conversation {
  schemaVersion: 1;
  conversationId: string;
  userId: number;
  auditingId: number;
  agentName: string;
  title?: string;
  createdAt: Date;
  updatedAt: Date;
  messageCount: number;
  metadata?: Record<string, any>;
}
Field Type Description
conversationId string Primary key. When a TraceStore is also used, this equals Trace.sessionId.
userId number User who owns this conversation.
auditingId number Auditing context identifier.
agentName string Which agent handles this conversation.
title string Auto-generated or user-set conversation title.
messageCount number Denormalized count for listing UIs.
metadata object Arbitrary metadata (e.g. default store, default parameters).

ConversationMessage

interface ConversationMessage {
  schemaVersion: 1;
  messageId: string;
  conversationId: string;
  role: ConversationRole;
  content: string;
  timestamp: Date;
  traceId?: string;
  sources?: Array<{
    documentId?: string;
    documentName?: string;
    chunk?: string;
    score?: number;
  }>;
  metadata?: Record<string, any>;
}
Field Type Description
messageId string Primary key (ULID recommended for natural sort order).
role ConversationRole "user", "assistant", or "system".
content string Message text content.
timestamp Date When the message was created.
traceId string Back-link to the trace that produced this assistant message.
sources array RAG sources returned with this assistant message.

ConversationRole

type ConversationRole = "user" | "assistant" | "system";

ConversationFilter

interface ConversationFilter {
  userId?: number;
  agentName?: string;
  limit?: number;   // Default: 50
  offset?: number;
}

MessageQueryOptions

interface MessageQueryOptions {
  limit?: number;
  before?: Date;
}
Option Type Description
limit number Maximum number of messages to return. Returns the most recent N messages (in ascending order).
before Date Return messages before this timestamp. Useful for pagination or context-window trimming.

Code Example

import type { ConversationStore } from "@modernpath/agent-framework";

async function sendMessage(
  store: ConversationStore,
  conversationId: string,
  userMessage: string,
  agent: BaseAgent,
) {
  // Load conversation history for agent context
  const messages = await store.getMessages(conversationId, { limit: 50 });
  const history = messages.map((m) => ({
    role: m.role,
    content: m.content,
    timestamp: m.timestamp,
  }));

  // Execute agent with history
  const result = await agent.execute({
    userId: 1,
    auditingId: 100,
    prompt: userMessage,
    parameters: {},
    history,
  });

  // Save user message
  await store.addMessage(conversationId, {
    schemaVersion: 1,
    messageId: crypto.randomUUID(),
    conversationId,
    role: "user",
    content: userMessage,
    timestamp: new Date(),
  });

  // Save assistant message
  await store.addMessage(conversationId, {
    schemaVersion: 1,
    messageId: crypto.randomUUID(),
    conversationId,
    role: "assistant",
    content: result.data?.answer ?? "",
    timestamp: new Date(),
    traceId: result.metadata?.traceId,
    sources: result.data?.sources,
  });

  return result;
}