Vector Storage

Table of contents

  1. Setup
    1. SQLite (default)
    2. PostgreSQL + pgvector
    3. In-memory (testing)
  2. Working with Collections
    1. Insert and upsert
    2. Semantic search
    3. Delete
  3. ICollection Reference
  4. Document Type Requirements
  5. Example: RAG Pipeline

Agentic provides a typed vector store abstraction (IStore / ICollection<T>) with two production-ready backends — SQLite and PostgreSQL + pgvector — plus an in-memory store for tests.

Setup

SQLite (default)

services.AddStore();

SQLite stores embeddings in a local .db file. No additional infrastructure required.

PostgreSQL + pgvector

// appsettings.json
{
  "Database": {
    "Provider": "postgres",
    "ConnectionString": "Host=localhost;Database=mydb;Username=postgres;Password=secret"
  }
}

// Program.cs
services.AddStore(configuration);

Requires the pgvector extension to be installed in your PostgreSQL database:

CREATE EXTENSION vector;

In-memory (testing)

services.AddInMemoryStore();

The in-memory store is non-persistent and ideal for unit tests and integration tests.

Working with Collections

Insert and upsert

var store    = services.BuildServiceProvider().GetRequiredService<IStore>();
var articles = store.Collection<Article>("articles");

// Insert a new document with its embedding
var id = await articles.InsertAsync(
    new Article { Title = "Hello", Body = "..." },
    embedding: embeddingVector);

// Update an existing document (keep same embedding)
await articles.UpsertAsync(id, new Article { Title = "Updated", Body = "..." });
var queryVector = await lm.EmbedAsync("search query text");

var results = await articles.SearchAsync(queryVector, topK: 5);
foreach (var r in results)
    Console.WriteLine($"{r.Score:F4}  {r.Document.Title}");

Delete

await articles.DeleteAsync(id);

ICollection Reference

MethodDescription
InsertAsync(doc, embedding)Insert a new document and store its embedding
UpsertAsync(id, doc)Update the document at id (embedding unchanged)
UpsertAsync(id, doc, embedding)Update the document and its embedding
DeleteAsync(id)Remove the document by ID
SearchAsync(queryVector, topK)Return the top-K most similar documents with similarity scores
GetAsync(id)Retrieve a document by ID

Document Type Requirements

Documents can be any C# class. No base class or interface is required — they are serialised to/from JSON:

public class Article
{
    public string Title  { get; set; } = "";
    public string Body   { get; set; } = "";
    public string Author { get; set; } = "";
    public DateTime PublishedAt { get; set; }
}

Example: RAG Pipeline

A complete Retrieval-Augmented Generation (RAG) pipeline using Agentic:

// 1. Index documents
var store    = sp.GetRequiredService<IStore>();
var articles = store.Collection<Article>("articles");

foreach (var article in myArticles)
{
    var embedding = await lm.EmbedAsync(article.Title + " " + article.Body);
    await articles.InsertAsync(article, embedding);
}

// 2. Retrieve relevant context
var queryEmbedding = await lm.EmbedAsync(userQuery);
var topResults     = await articles.SearchAsync(queryEmbedding, topK: 3);

var context = string.Join("\n\n", topResults.Select(r =>
    $"Title: {r.Document.Title}\n{r.Document.Body}"));

// 3. Answer with context
var agent = new Agent(lm, new AgentOptions
{
    SystemPrompt =
        $"You are a helpful assistant. Use the following context to answer questions:\n\n{context}",
});

await agent.ChatStreamAsync(userQuery);