@happyvertical/smrt-chat

Chat rooms, DMs, threads, and agent conversations with tool whitelisting for the SMRT framework.

v0.20.44RoomsThreadsAgent Sessions

Overview

smrt-chat provides multi-tenant chat infrastructure with support for public and private rooms, direct messages, threaded conversations, reactions, and AI agent sessions with configurable tool access.

Installation

bash
npm install @happyvertical/smrt-chat

Quick Start

typescript
import { ChatService } from '@happyvertical/smrt-chat';

const chat = await ChatService.create({
  persistence: { type: 'sql', url: 'chat.db' },
});

// Create a public room (creator added as owner)
const room = await chat.createRoom({
  tenantId: 'tenant-1',
  name: 'General',
  roomType: 'public',
  createdByProfileId: 'profile-1',
});

// Send a message
await chat.sendMessage({
  tenantId: 'tenant-1',
  roomId: room.id,
  senderProfileId: 'profile-1',
  content: 'Hello, world!',
});

// Start a threaded conversation
const thread = await chat.startThread({
  tenantId: 'tenant-1',
  roomId: room.id,
  rootMessageId: message.id,
  title: 'Follow-up discussion',
});

// Reply within the thread
await chat.sendMessage({
  tenantId: 'tenant-1',
  roomId: room.id,
  senderProfileId: 'profile-2',
  content: 'Great point!',
  threadId: thread.id,
});

// Get or create a DM room between two profiles
const dmRoom = await chat.getOrCreateDM({
  tenantId: 'tenant-1',
  profileId1: 'profile-1',
  profileId2: 'profile-2',
});

Core Models

ChatRoom

typescript
class ChatRoom extends SmrtObject {
  name: string
  roomType: 'public' | 'private' | 'dm' | 'agent'
  status: string
  topic?: string
  maxParticipants?: number
  lastMessageAt?: Date

  // Tenant-scoped (required)
}

ChatMessage

typescript
class ChatMessage extends SmrtObject {
  roomId: string
  senderProfileId: string
  content: string
  role: 'user' | 'assistant' | 'system' | 'tool'
  messageType: 'text' | 'system' | 'action' | 'file' | 'tool_call' | 'tool_result'
  threadId?: string
  replyToMessageId?: string
  toolCallData?: string       // JSON for tool interactions
}

AgentSession

typescript
class AgentSession extends SmrtObject {
  agentId: string             // String ref (not FK)
  roomId: string
  allowedTools: string        // JSON string array
  sessionContext: string      // JSON for multi-turn memory
  systemPrompt?: string
  maxTokens?: number
  maxMessages?: number
  expiresAt?: Date
  status: string

  isActive(): boolean
  getAllowedTools(): string[]
  getSessionContext(): Record<string, any>
  updateSessionContext(updates: Record<string, any>): void
}

Agent Sessions

typescript
// Create an agent session (auto-creates an agent-type room)
const { session, room } = await chat.createAgentSession({
  tenantId: 'tenant-1',
  agentId: 'agent-summarizer',
  participantProfileId: 'profile-1',
  allowedTools: ['web-search', 'summarize'],
  systemPrompt: 'You are a research assistant.',
  maxMessages: 100,
});

// Send a message within the agent session
await chat.sendAgentMessage({
  tenantId: 'tenant-1',
  agentSessionId: session.id,
  senderProfileId: 'profile-1',
  content: 'Summarize the latest news',
  role: 'user',
});

// Check session limits before allowing more messages
if (session.isActive()) {
  // Session has not expired or hit token/message limits
}

// Tool whitelisting is app-controlled:
// The framework stores the allowedTools list but
// the consuming app validates before execution

Best Practices

DOs

  • Use ChatService facade for room creation and messaging
  • Check session.isActive() before sending agent messages
  • Use getSessionContext()/updateSessionContext() for agent memory
  • Validate tool calls against allowedTools in your app logic
  • Use getOrCreateDM() for direct message rooms

DON'Ts

  • Don't use context field directly (reserved for slug scoping -- use sessionContext)
  • Don't skip session expiry checks (expiresAt or limit-based)
  • Don't rely on framework for tool validation (app responsibility)
  • Don't forget tenant context (ChatRoom requires tenant scoping)
  • Don't create agent rooms manually (use createAgentSession which auto-creates them)

Related Modules