npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

pg-agent-memory

v1.1.4

Published

Stateful AI agent memory layer for PostgreSQL with pgvector - TypeScript-first with intelligent context management

Downloads

96

Readme

pg-agent-memory

Stateful AI agent memory layer for PostgreSQL with pgvector. TypeScript-first with intelligent context management and semantic search.

npm version Downloads License: MIT Node.js CI Test Coverage TypeScript Node.js

Why pg-agent-memory?

The Problem: AI Agents Forget Everything

❌ Without pg-agent-memory

// Day 1: User shares preference
await openai.chat.completions.create({
  messages: [{ role: 'user', content: 'I prefer Python' }],
});
// AI: "Got it! I'll remember that."

// Day 2: User asks for help
await openai.chat.completions.create({
  messages: [{ role: 'user', content: 'Help me start a project' }],
});
// AI: "What language would you like to use?"
// 😤 Forgot everything!

✅ With pg-agent-memory

// Day 1: Store preference
await memory.remember({
  conversation: userId,
  content: 'User prefers Python',
  role: 'system',
});

// Day 2: Retrieve context
const context = await memory.getHistory(userId);
await openai.chat.completions.create({
  messages: [...context, { role: 'user', content: 'Help me start a project' }],
});
// AI: "I'll create a Python project for you!"
// 🎯 Remembers everything!

Features

  • Persistent Memory - Conversations continue across sessions
  • Multi-Model Support - OpenAI, Anthropic, DeepSeek, Google, Meta + custom providers
  • Local Embeddings - Zero API costs for vector embeddings with Sentence Transformers
  • Memory Compression - Automatic summarization with 4 compression strategies
  • Semantic Search - Find relevant memories using AI embeddings
  • Universal Tokenizer - Accurate token counting based on official provider documentation
  • TypeScript First - Full type safety with autocomplete
  • PostgreSQL Native - Uses your existing database
  • Zero-Cost Embeddings - Local Sentence Transformers (@xenova/transformers)
  • High Performance - ~9ms memory operations, ~5ms vector search

Coming Soon

  • Multi-agent memory sharing
  • Memory graph visualization
  • Pattern detection

Quick Start

# Install
npm install pg-agent-memory

# Start PostgreSQL with Docker (includes pgvector)
docker compose up -d

# Run example
npm start

Installation

npm install pg-agent-memory

Database Setup

Option 1: Docker (Recommended)

# Use included docker compose configuration
docker compose up -d

Option 2: Existing PostgreSQL

-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

Basic Usage

import { AgentMemory } from 'pg-agent-memory';

// Option 1: Static factory method (recommended)
const memory = await AgentMemory.create({
  agent: 'my-assistant',
  connectionString: 'postgresql://user:pass@localhost:5432/db',
});

// Option 2: Traditional constructor + initialize
const memory = new AgentMemory({
  agent: 'my-assistant',
  connectionString: 'postgresql://user:pass@localhost:5432/db',
});
await memory.initialize();

// Store conversation memory
const memoryId = await memory.remember({
  conversation: 'user-123',
  content: 'User prefers email notifications',
  role: 'user',
  importance: 0.8,
  timestamp: new Date(),
});

// Find related memories using vector similarity
const related = await memory.findRelatedMemories(memoryId, 5);

// Semantic search across memories
const relevant = await memory.searchMemories('notification preferences');

// Get relevant context for a query
const context = await memory.getRelevantContext(
  'user-123',
  'user communication preferences',
  1000 // max tokens
);

console.log(`Found ${context.messages.length} relevant memories`);
console.log(`Relevance score: ${context.relevanceScore}`);

// Health check for monitoring
const health = await memory.healthCheck();
console.log(`Status: ${health.status}, Memories: ${health.details.memoryCount}`);

// Cleanup
await memory.disconnect();

Multi-Model Support

Configure multiple AI providers with accurate token counting and prompt caching:

const memory = new AgentMemory({
  agent: 'multi-model-bot',
  connectionString,
  modelProviders: [
    {
      name: 'gpt-4o',
      provider: 'openai',
      model: 'gpt-4o',
      tokenLimits: { context: 128000, output: 4000 },
      // High context limit: Supports large conversations
    },
    {
      name: 'claude-sonnet',
      provider: 'anthropic',
      model: 'claude-sonnet-4-20250514',
      tokenLimits: { context: 200000, output: 4000 },
      // Large context window: Perfect for long conversations
    },
    {
      name: 'deepseek-coder',
      provider: 'deepseek',
      model: 'deepseek-coder',
      tokenLimits: { context: 32000, output: 4000 },
      // Cost-effective option for coding tasks
    },
    {
      name: 'gemini-pro',
      provider: 'google',
      model: 'gemini-1.5-pro',
      tokenLimits: { context: 1048576, output: 8192 },
      // Massive context window: Handle very long conversations
    },
    {
      name: 'llama-3',
      provider: 'meta',
      model: 'llama-3.1-70b',
      tokenLimits: { context: 128000, output: 4000 },
      // More efficient tokenizer: ~44% fewer tokens than OpenAI
    },
  ],
  defaultProvider: 'gpt-4o',
  tokenCountingStrategy: 'hybrid', // 'precise', 'fast', or 'hybrid'
});

// Token counting uses official provider documentation:
// - OpenAI: ~4 chars/token or 0.75 words/token (official baseline)
// - Anthropic: ~3.5 chars/token (14% more tokens)
// - DeepSeek: ~3.3 chars/token (20% more tokens)
// - Google: ~4 chars/token (same as OpenAI)
// - Meta/Llama: ~0.75 tokens/word (44% fewer tokens - more efficient)
await memory.remember({
  conversation: userId,
  content: longText,
  provider: 'gpt-4o', // Use OpenAI for this memory
});

Memory Compression

Automatic memory compression with multiple strategies:

// Enable compression for large conversations
const compressionResult = await memory.compressMemories({
  strategy: 'hybrid', // 'token_based', 'time_based', 'importance_based', 'hybrid'
  maxAge: '7d',
  targetCompressionRatio: 0.6,
});

console.log(`Compressed ${compressionResult.memoriesCompressed} memories`);
console.log(`Token savings: ${compressionResult.tokensSaved}`);

// Get context with automatic compression
const context = await memory.getRelevantContextWithCompression(
  'coding preferences',
  4000 // Automatically compresses if needed
);

Real-World Integration

With OpenAI

import OpenAI from 'openai';
import { AgentMemory } from 'pg-agent-memory';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const memory = new AgentMemory({ agent: 'support-bot', connectionString });

// Retrieve conversation history
const history = await memory.getHistory(userId);

// Include memory in AI request
const completion = await client.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    ...history.map(m => ({ role: m.role, content: m.content })),
    { role: 'user', content: userMessage },
  ],
});

// Store the interaction
await memory.remember({
  conversation: userId,
  content: userMessage,
  role: 'user',
  importance: 0.5,
  timestamp: new Date(),
});

await memory.remember({
  conversation: userId,
  content: completion.choices[0].message.content,
  role: 'assistant',
  importance: 0.7,
  timestamp: new Date(),
});

With Anthropic Claude

import Anthropic from '@anthropic-ai/sdk';
import { AgentMemory } from 'pg-agent-memory';

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const memory = new AgentMemory({
  agent: 'claude-assistant',
  connectionString,
  modelProviders: [
    {
      name: 'claude',
      provider: 'anthropic',
      model: 'claude-sonnet-4-20250514',
      tokenLimits: { context: 200000, output: 4000 },
    },
  ],
});

// Get conversation with compression for large contexts
const context = await memory.getRelevantContextWithCompression(
  'user preferences and history',
  180000 // Near Claude's context limit
);

const message = await client.messages.create({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1024,
  messages: [
    ...context.messages.map(m => ({ role: m.role, content: m.content })),
    { role: 'user', content: userMessage },
  ],
});

// Store the interaction
await memory.remember({
  conversation: userId,
  content: message.content[0].text,
  role: 'assistant',
  importance: 0.7,
  timestamp: new Date(),
});

With Vercel AI SDK

import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { AgentMemory } from 'pg-agent-memory';

const memory = new AgentMemory({ agent: 'chat-assistant', connectionString });

export async function POST(req: Request) {
  const { messages, userId } = await req.json();

  // Get user's conversation history
  const history = await memory.getHistory(userId);

  const result = streamText({
    model: openai('gpt-4o'),
    system: 'You are a helpful assistant with memory.',
    messages: [...history, ...messages],
  });

  // Store the conversation
  for (const message of messages) {
    await memory.remember({
      conversation: userId,
      role: message.role,
      content: message.content,
      importance: 0.5,
      timestamp: new Date(),
    });
  }

  return result.toDataStreamResponse();
}

API Reference

AgentMemory

Static Methods

AgentMemory.create(config: MemoryConfig): Promise<AgentMemory>

Recommended: Creates and initializes an AgentMemory instance in one call.

const memory = await AgentMemory.create({
  agent: 'my-bot',
  connectionString: 'postgresql://...',
});

Constructor

new AgentMemory(config: MemoryConfig)

MemoryConfig:

  • agent: string - Unique agent identifier
  • connectionString: string - PostgreSQL connection string
  • tablePrefix?: string - Table prefix (default: 'agent')
  • maxTokens?: number - Max tokens per memory (default: 4000)
  • embeddingDimensions?: number - Vector dimensions (default: 384)

Core Methods

initialize(): Promise<void>

Initialize database schema and embedding model.

remember(message: Message): Promise<string>

Store a conversation memory.

findRelatedMemories(memoryId: string, limit?: number): Promise<Message[]>

Find memories related to a specific memory using vector similarity.

const related = await memory.findRelatedMemories(memoryId, 5);
healthCheck(): Promise<HealthStatus>

Check system health for monitoring and debugging.

const health = await memory.healthCheck();
// Returns: { status: 'healthy' | 'unhealthy', details: {...} }

Message:

{
  conversation: string;    // Conversation ID
  content: string;         // Memory content
  role: 'user' | 'assistant' | 'system'; // Required, defaults to 'user'
  importance: number;      // 0-1 relevance score, defaults to 0.5
  timestamp: Date;         // Required, defaults to new Date()
  id?: string;             // Optional memory ID
  metadata?: Record<string, unknown>;
  embedding?: number[];    // Optional vector embedding
  expires?: Date | string; // Expiration (e.g., '30d', '1h')
}
recall(filter: MemoryFilter): Promise<Context>

Retrieve memories with filtering.

getHistory(conversation: string, limit?: number): Promise<Message[]>

Get chronological conversation history.

getRelevantContext(conversation: string, query: string, maxTokens: number): Promise<Context>

Find semantically relevant memories for a query.

searchMemories(query: string, filters?: MemoryFilter): Promise<Message[]>

Semantic search across all agent memories.

deleteMemory(memoryId: string): Promise<void>

Delete specific memory.

deleteConversation(conversation: string): Promise<void>

Delete entire conversation.

Database Requirements

  • PostgreSQL 12+
  • pgvector extension

Performance

  • Memory operations: ~9ms average (range: 5-22ms, first operation slower due to model loading)
  • Vector search: ~5ms average for semantic similarity search using pgvector
  • Token counting: <1ms sub-millisecond performance for all text sizes
  • Embedding generation: Local processing, no API calls required
  • Model size: ~80-90MB (all-MiniLM-L6-v2, cached after first download)
  • Architecture: Built for production scale with proper indexing and connection pooling

Architecture

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   AgentMemory   │────│  EmbeddingService │────│ @xenova/trans.. │
│                 │    │                  │    │   (Local Model) │
└─────────────────┘    └──────────────────┘    └─────────────────┘
         │
         ▼
┌─────────────────┐    ┌──────────────────┐
│   PostgreSQL    │────│     pgvector     │
│   (Memories)    │    │  (Vector Search) │
└─────────────────┘    └──────────────────┘

Components:

  • AgentMemory: Main API for memory operations
  • EmbeddingService: Local text-to-vector conversion using @xenova/transformers
  • PostgreSQL: Persistent storage with ACID properties
  • pgvector: Efficient vector similarity search
  • @xenova/transformers: Local Sentence Transformers model (all-MiniLM-L6-v2)

Examples

Chatbot Integration

import { AgentMemory } from 'pg-agent-memory';

class ChatBot {
  private memory: AgentMemory;

  constructor() {
    this.memory = new AgentMemory({
      agent: 'chatbot',
      connectionString: process.env.DATABASE_URL,
    });
  }

  async processMessage(userId: string, message: string) {
    // Store user message
    await this.memory.remember({
      conversation: userId,
      content: message,
      role: 'user',
      importance: 0.5,
      timestamp: new Date(),
    });

    // Get relevant context
    const context = await this.memory.getRelevantContext(userId, message, 800);

    // Generate response using context
    const response = await this.generateResponse(message, context);

    // Store bot response
    await this.memory.remember({
      conversation: userId,
      content: response,
      role: 'assistant',
      importance: 0.7,
      timestamp: new Date(),
    });

    return response;
  }
}

Advanced Filtering

// Search with filters
const memories = await memory.searchMemories('user preferences', {
  importance: { min: 0.7 },
  dateRange: {
    start: new Date('2024-01-01'),
    end: new Date('2024-12-31'),
  },
  metadata: { category: 'user_settings' },
  limit: 10,
});

// Get memories by role
const userMessages = await memory.recall({
  conversation: 'user-123',
  role: 'user',
  limit: 50,
});

Running Examples

# Set database URL
export DATABASE_URL="postgresql://user:pass@localhost:5432/dbname"

# Run basic example
npm run example:basic

# Run chatbot example
npm run example:chatbot

# Run all examples
npm run example:all

Development

Quick Start with Docker

# Clone repository
git clone <repository>
cd pg-agent-memory
npm install

# Start PostgreSQL with pgvector
npm run dev:up

# Copy environment variables
cp .env.example .env

# Run examples
npm run example:basic

# Run tests
npm run test:docker

Docker Commands

# Start development database
npm run dev:up

# Stop database (data persists)
npm run dev:down

# View database logs
npm run dev:logs

# Clean everything (including data)
npm run dev:clean

# Connect to PostgreSQL shell
bash scripts/docker-dev.sh shell

Manual Setup

If you prefer using your own PostgreSQL:

# Install pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

# Set connection string
export DATABASE_URL="postgresql://user:pass@localhost:5432/dbname"

# Run tests
npm test
npm run test:integration

Testing

# Unit tests (no database needed)
npm test

# Integration tests with Docker
npm run test:docker

# Integration tests with custom database
export DATABASE_URL="postgresql://user:pass@localhost:5432/test_db"
npm run test:integration

# All tests
npm run test:all

# Code quality checks
npm run lint           # ESLint + Prettier
npm run type-check     # TypeScript compilation
npm run validate       # Full validation (lint + type-check + tests)

# Performance benchmarks
npm run benchmark      # Verify performance claims

License

MIT © Alex Potapenko

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Run tests: npm test
  4. Submit a pull request

Support