Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .changeset/five-eggs-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
"@voltagent/postgres": patch
---

feat: add PostgresVectorAdapter for semantic search with vanilla PostgreSQL

## What Changed for You

The `@voltagent/postgres` package now includes `PostgresVectorAdapter` for storing and querying vector embeddings using vanilla PostgreSQL (no extensions required). This enables semantic search capabilities for conversation history, allowing agents to retrieve contextually relevant messages based on meaning rather than just keywords.

## New: PostgresVectorAdapter

```typescript
import { Agent, Memory, AiSdkEmbeddingAdapter } from "@voltagent/core";
import { PostgresMemoryAdapter, PostgresVectorAdapter } from "@voltagent/postgres";
import { openai } from "@ai-sdk/openai";

const memory = new Memory({
storage: new PostgresMemoryAdapter({
connectionString: process.env.DATABASE_URL,
}),
embedding: new AiSdkEmbeddingAdapter(openai.embedding("text-embedding-3-small")),
vector: new PostgresVectorAdapter({
connectionString: process.env.DATABASE_URL,
}),
});

const agent = new Agent({
name: "Assistant",
instructions: "You are a helpful assistant with semantic memory",
model: openai("gpt-4o-mini"),
memory,
});

// Semantic search automatically enabled with userId + conversationId
const result = await agent.generateText("What did we discuss about the project?", {
userId: "user-123",
conversationId: "conv-456",
});
```

## Key Features

- **No Extensions Required**: Works with vanilla PostgreSQL (no pgvector needed)
- **BYTEA Storage**: Vectors stored efficiently as binary data using PostgreSQL's native BYTEA type
- **In-Memory Similarity**: Cosine similarity computed in-memory for accurate results
- **Automatic Setup**: Creates `voltagent_vectors` table and indexes automatically
- **Configurable**: Customize table name, vector dimensions, cache size, and retry logic
- **Production Ready**: Connection pooling, exponential backoff, LRU caching

## Configuration Options

```typescript
const vectorAdapter = new PostgresVectorAdapter({
connectionString: process.env.DATABASE_URL,

// Optional: customize table name (default: "voltagent_vector")
tablePrefix: "custom_vector",

// Optional: vector dimensions (default: 1536 for text-embedding-3-small)
maxVectorDimensions: 1536,

// Optional: LRU cache size (default: 100)
cacheSize: 100,

// Optional: connection pool size (default: 10)
maxConnections: 10,
});
```

## How It Works

1. **Embedding Generation**: Messages are converted to vector embeddings using your chosen embedding model
2. **Binary Storage**: Vectors are serialized to binary (BYTEA) and stored in PostgreSQL
3. **In-Memory Similarity**: When searching, all vectors are loaded and cosine similarity is computed in-memory
4. **Context Merging**: Relevant messages are merged into conversation context automatically

## Why This Matters

- **Better Context Retrieval**: Find relevant past conversations even with different wording
- **Unified Storage**: Keep vectors and messages in the same PostgreSQL database
- **Zero Extensions**: Works with any PostgreSQL instance (12+), no extension installation needed
- **Cost Effective**: No separate vector database needed (Pinecone, Weaviate, etc.)
- **Familiar Tools**: Use standard PostgreSQL management and monitoring tools
- **Framework Parity**: Same `VectorStorageAdapter` interface as other providers

## Performance Notes

This adapter loads all vectors into memory for similarity computation, which works well for:

- **Small to medium datasets** (< 10,000 vectors)
- **Development and prototyping**
- **Applications where extension installation is not possible**

For large-scale production workloads with millions of vectors, consider specialized vector databases or PostgreSQL with pgvector extension for database-level similarity operations.

## Migration Notes

Existing PostgreSQL memory adapters continue to work without changes. Vector storage is optional and only activates when you configure both `embedding` and `vector` in the Memory constructor.
149 changes: 149 additions & 0 deletions .changeset/real-olives-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
"@voltagent/voltagent-memory": patch
"@voltagent/core": patch
---

feat: introduce managed memory - ready-made cloud storage for VoltAgent

## What Changed for You

VoltAgent now offers a managed memory solution that eliminates the need to run your own database infrastructure. The new `@voltagent/voltagent-memory` package provides a `ManagedMemoryAdapter` that connects to VoltOps Managed Memory service, perfect for pilots, demos, and production workloads.

## New Package: @voltagent/voltagent-memory

### Automatic Setup (Recommended)

Get your credentials from [console.voltagent.dev/memory/managed-memory](https://console.voltagent.dev/memory/managed-memory) and set environment variables:

```bash
# .env
VOLTAGENT_PUBLIC_KEY=pk_...
VOLTAGENT_SECRET_KEY=sk_...
```

```typescript
import { Agent, Memory } from "@voltagent/core";
import { ManagedMemoryAdapter } from "@voltagent/voltagent-memory";
import { openai } from "@ai-sdk/openai";

// Adapter automatically uses VoltOps credentials from environment
const agent = new Agent({
name: "Assistant",
instructions: "You are a helpful assistant",
model: openai("gpt-4o-mini"),
memory: new Memory({
storage: new ManagedMemoryAdapter({
databaseName: "production-memory",
}),
}),
});

// Use like any other agent - memory is automatically persisted
const result = await agent.generateText("Hello!", {
userId: "user-123",
conversationId: "conv-456",
});
```

### Manual Setup

Pass a `VoltOpsClient` instance explicitly:

```typescript
import { Agent, Memory, VoltOpsClient } from "@voltagent/core";
import { ManagedMemoryAdapter } from "@voltagent/voltagent-memory";
import { openai } from "@ai-sdk/openai";

const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTAGENT_PUBLIC_KEY!,
secretKey: process.env.VOLTAGENT_SECRET_KEY!,
});

const agent = new Agent({
name: "Assistant",
instructions: "You are a helpful assistant",
model: openai("gpt-4o-mini"),
memory: new Memory({
storage: new ManagedMemoryAdapter({
databaseName: "production-memory",
voltOpsClient, // explicit client
}),
}),
});
```

### Vector Storage (Optional)

Enable semantic search with `ManagedMemoryVectorAdapter`:

```typescript
import { ManagedMemoryAdapter, ManagedMemoryVectorAdapter } from "@voltagent/voltagent-memory";
import { AiSdkEmbeddingAdapter, Memory } from "@voltagent/core";
import { openai } from "@ai-sdk/openai";

const memory = new Memory({
storage: new ManagedMemoryAdapter({
databaseName: "production-memory",
}),
embedding: new AiSdkEmbeddingAdapter(openai.embedding("text-embedding-3-small")),
vector: new ManagedMemoryVectorAdapter({
databaseName: "production-memory",
}),
});
```

## Key Features

- **Zero Infrastructure**: No need to provision or manage databases
- **Quick Setup**: Create a managed memory database in under 3 minutes from VoltOps Console
- **Framework Parity**: Works identically to local Postgres, LibSQL, or Supabase adapters
- **Production Ready**: Managed infrastructure with reliability guardrails
- **Multi-Region**: Available in US (Virginia) and EU (Germany)

## Getting Started

1. **Install the package**:

```bash
npm install @voltagent/voltagent-memory
# or
pnpm add @voltagent/voltagent-memory
```

2. **Create a managed database**:
- Navigate to [console.voltagent.dev/memory/managed-memory](https://console.voltagent.dev/memory/managed-memory)
- Click **Create Database**
- Enter a name and select region (US or EU)
- Copy your VoltOps API keys from Settings

3. **Configure environment variables**:

```bash
VOLTAGENT_PUBLIC_KEY=pk_...
VOLTAGENT_SECRET_KEY=sk_...
```

4. **Use the adapter**:

```typescript
import { ManagedMemoryAdapter } from "@voltagent/voltagent-memory";
import { Memory } from "@voltagent/core";

const memory = new Memory({
storage: new ManagedMemoryAdapter({
databaseName: "your-database-name",
}),
});
```

## Why This Matters

- **Faster Prototyping**: Launch pilots without database setup
- **Reduced Complexity**: No infrastructure management overhead
- **Consistent Experience**: Same StorageAdapter interface across all memory providers
- **Scalable Path**: Start with managed memory, migrate to self-hosted when needed
- **Multi-Region Support**: Deploy close to your users in US or EU

## Migration Notes

Existing agents using local storage adapters (InMemory, LibSQL, Postgres, Supabase) continue to work unchanged. Managed memory is an optional addition that provides a cloud-hosted alternative for teams who prefer not to manage their own database infrastructure.
16 changes: 8 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3992,8 +3992,8 @@

// 1. Initialize VoltOps client
const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTOPS_PUBLIC_KEY,
secretKey: process.env.VOLTOPS_SECRET_KEY,
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
});

// 2. Create agent with VoltOps prompts
Expand Down Expand Up @@ -4031,8 +4031,8 @@
import { Agent, VoltAgent, VoltOpsClient } from "@voltagent/core";

const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTOPS_PUBLIC_KEY,
secretKey: process.env.VOLTOPS_SECRET_KEY,
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
observability: true, // Enable observability - default is true
prompts: true, // Enable prompt management - default is true
});
Expand All @@ -4056,8 +4056,8 @@
agents: { myAgent },
- telemetryExporter: new VoltAgentExporter({
+ voltOpsClient: new VoltOpsClient({
publicKey: process.env.VOLTOPS_PUBLIC_KEY,
secretKey: process.env.VOLTOPS_SECRET_KEY,
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
- baseUrl: "https://api.voltagent.dev",
}),
});
Expand Down Expand Up @@ -4087,8 +4087,8 @@

```typescript
const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTOPS_PUBLIC_KEY,
secretKey: process.env.VOLTOPS_SECRET_KEY,
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
baseUrl: "https://api.voltagent.dev", // Default
observability: true, // Enable observability export - default is true
prompts: false, // Observability only - default is true
Expand Down
4 changes: 2 additions & 2 deletions examples/with-dynamic-prompts/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OPENAI_API_KEY=your_openai_api_key_here

VOLTOPS_PUBLIC_KEY=your_voltops_public_key
VOLTOPS_SECRET_KEY=your_voltops_secret_key
VOLTAGENT_PUBLIC_KEY=your_VOLTAGENT_PUBLIC_KEY
VOLTAGENT_SECRET_KEY=your_VOLTAGENT_SECRET_KEY
4 changes: 2 additions & 2 deletions examples/with-dynamic-prompts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const logger = createPinoLogger({
});

const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTOPS_PUBLIC_KEY,
secretKey: process.env.VOLTOPS_SECRET_KEY,
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
});

const supportAgent = new Agent({
Expand Down
4 changes: 2 additions & 2 deletions examples/with-viteval/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OPENAI_API_KEY=sk-svcacct-your_openai_api_key_here
VOLTOPS_PUBLIC_KEY=pk_your_public_key_here
VOLTOPS_SECRET_KEY=sk_your_secret_key_here
VOLTAGENT_PUBLIC_KEY=pk_your_public_key_here
VOLTAGENT_SECRET_KEY=sk_your_secret_key_here

8 changes: 4 additions & 4 deletions examples/with-viteval/src/voltagent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { scienceAgent } from "#/agents/science";
import { supervisorAgent } from "#/agents/supervisor";

const env = cleanEnv(process.env, {
VOLTOPS_PUBLIC_KEY: str(),
VOLTOPS_SECRET_KEY: str(),
VOLTAGENT_PUBLIC_KEY: str(),
VOLTAGENT_SECRET_KEY: str(),
});

export const voltagent = new VoltAgent({
Expand All @@ -24,8 +24,8 @@ export const voltagent = new VoltAgent({
science: scienceAgent,
},
voltOpsClient: new VoltOpsClient({
publicKey: env.VOLTOPS_PUBLIC_KEY,
secretKey: env.VOLTOPS_SECRET_KEY,
publicKey: env.VOLTAGENT_PUBLIC_KEY,
secretKey: env.VOLTAGENT_SECRET_KEY,
}),
server: honoServer(),
});
6 changes: 6 additions & 0 deletions examples/with-voltagent-managed-memory/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
VOLTAGENT_PUBLIC_KEY=pk_xxxxxxxxxxxxxxxxxxxxx
VOLTAGENT_SECRET_KEY=sk_xxxxxxxxxxxxxxxxxxxxx
VOLTOPS_API_URL=https://api.voltagent.dev
MANAGED_MEMORY_DB_NAME=production-memory
PORT=3141
LOG_LEVEL=info
Loading