HnswLite.Sdk 2.1.0

dotnet add package HnswLite.Sdk --version 2.1.0
                    
NuGet\Install-Package HnswLite.Sdk -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HnswLite.Sdk" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HnswLite.Sdk" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="HnswLite.Sdk" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HnswLite.Sdk --version 2.1.0
                    
#r "nuget: HnswLite.Sdk, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HnswLite.Sdk@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HnswLite.Sdk&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=HnswLite.Sdk&version=2.1.0
                    
Install as a Cake Tool

HnswLite C# SDK

C# SDK for the HnswLite REST API. Provides full async coverage of every endpoint for index management, vector operations, and K-nearest-neighbour search.

Installation

dotnet add package HnswLite.Sdk

Or via the NuGet Package Manager:

Install-Package HnswLite.Sdk

Quick Start

using HnswLite.Sdk;
using HnswLite.Sdk.Models;

using HnswLiteClient client = new HnswLiteClient(
    baseUrl: "http://localhost:8080",
    apiKey: "your-api-key"
);

Usage Examples

Health Check (Ping)

// GET / — unauthenticated health ping
bool isAlive = await client.PingAsync();
Console.WriteLine("Server alive: " + isAlive);

// HEAD / — unauthenticated head ping
bool headOk = await client.HeadPingAsync();

Create an Index

IndexResponse index = await client.CreateIndexAsync(new CreateIndexRequest
{
    Name = "my-index",
    Dimension = 384,
    StorageType = "PostgreSQL",    // "PostgreSQL", "SQLite", or "RAM"
    DistanceFunction = "Cosine",   // "Euclidean", "Cosine", or "DotProduct"
    M = 16,
    MaxM = 32,
    EfConstruction = 200
});

Console.WriteLine("Created index: " + index.Name + " (GUID: " + index.GUID + ")");

Get an Index

IndexResponse index = await client.GetIndexAsync("my-index");
Console.WriteLine("Vectors: " + index.VectorCount);

Enumerate Indexes

EnumerationResult<IndexResponse> page = await client.EnumerateIndexesAsync(new EnumerationQuery
{
    MaxResults = 25,
    Skip = 0,
    Ordering = EnumerationOrderEnum.NameAscending,
    Prefix = "prod-"
});

foreach (IndexResponse idx in page.Objects)
{
    Console.WriteLine(idx.Name + " (" + idx.VectorCount + " vectors)");
}

Console.WriteLine("End of results: " + page.EndOfResults);
Console.WriteLine("Total records: " + page.TotalRecords);

Add a Single Vector

AddVectorRequest echo = await client.AddVectorAsync("my-index", new AddVectorRequest
{
    Vector = new List<float> { 0.1f, 0.2f, 0.3f /* ... */ }
});

Console.WriteLine("Added vector GUID: " + echo.GUID);

Add a Batch of Vectors

AddVectorsRequest batchEcho = await client.AddVectorsAsync("my-index", new AddVectorsRequest
{
    Vectors = new List<AddVectorRequest>
    {
        new AddVectorRequest { Vector = new List<float> { 0.1f, 0.2f, 0.3f } },
        new AddVectorRequest { Vector = new List<float> { 0.4f, 0.5f, 0.6f } },
        new AddVectorRequest { Vector = new List<float> { 0.7f, 0.8f, 0.9f } }
    }
});

Console.WriteLine("Added " + batchEcho.Vectors.Count + " vectors");

Search (K-Nearest Neighbours)

SearchResponse result = await client.SearchAsync("my-index", new SearchRequest
{
    Vector = new List<float> { 0.1f, 0.2f, 0.3f /* ... */ },
    K = 10,
    Ef = 200  // optional; null uses server default
});

Console.WriteLine("Search took " + result.SearchTimeMs + " ms");

foreach (VectorSearchResult r in result.Results)
{
    Console.WriteLine("  GUID: " + r.GUID + " Distance: " + r.Distance);
}

Filter by Labels and Tags (v1.2+)

SearchRequest and EnumerationQuery both accept optional Labels, Tags, and CaseInsensitive fields. Filters use AND semantics across both — a record is kept only when every supplied label is present AND every supplied tag key/value matches. The response exposes a FilteredCount reporting how many candidates were dropped.

SearchResponse result = await client.SearchAsync("my-index", new SearchRequest
{
    Vector = new List<float> { 0.1f, 0.2f, 0.3f, 0.4f },
    K = 10,
    Labels = new List<string> { "red", "small" },
    Tags = new Dictionary<string, string> { { "env", "prod" } },
    CaseInsensitive = false,
});

Console.WriteLine($"Matches: {result.Results.Count}, filtered out: {result.FilteredCount}");

Enumerate Vectors

// GUIDs only (includeVectors defaults to false)
EnumerationResult<VectorEntryResponse> page = await client.EnumerateVectorsAsync(
    "my-index",
    new EnumerationQuery { MaxResults = 50 });

Console.WriteLine("Total vectors: " + page.TotalRecords);
foreach (VectorEntryResponse v in page.Objects)
{
    Console.WriteLine("  GUID: " + v.GUID);
}

// Include the full vector values
EnumerationResult<VectorEntryResponse> detailed = await client.EnumerateVectorsAsync(
    "my-index",
    new EnumerationQuery { MaxResults = 10 },
    includeVectors: true);

foreach (VectorEntryResponse v in detailed.Objects)
{
    Console.WriteLine("  GUID: " + v.GUID + " Dim: " + v.Vector.Count);
}

Get a Single Vector

Guid vectorId = Guid.Parse("...");
VectorEntryResponse entry = await client.GetVectorAsync("my-index", vectorId);

Console.WriteLine("GUID: " + entry.GUID);
Console.WriteLine("Vector: [" + string.Join(", ", entry.Vector) + "]");

Remove a Vector

Guid vectorId = Guid.Parse("...");
await client.RemoveVectorAsync("my-index", vectorId);

Delete an Index

await client.DeleteIndexAsync("my-index");

Error Handling

All non-2xx responses throw HnswLiteApiException:

try
{
    IndexResponse index = await client.GetIndexAsync("nonexistent");
}
catch (HnswLiteApiException ex)
{
    Console.WriteLine("Status: " + (int)ex.StatusCode);  // e.g. 404
    Console.WriteLine("Error:  " + ex.Error);             // e.g. "IndexNotFound"
    Console.WriteLine("Detail: " + ex.ApiMessage);        // Human-readable message
}

Cancellation

Every async method accepts an optional CancellationToken:

using CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
IndexResponse index = await client.GetIndexAsync("my-index", cts.Token);

Custom API Key Header

The API key header name is configurable (defaults to x-api-key):

using HnswLiteClient client = new HnswLiteClient(
    baseUrl: "http://localhost:8080",
    apiKey: "your-api-key",
    apiKeyHeader: "Authorization"
);

Running the Test Harness

cd sdk/csharp/HnswLite.Sdk.Test
dotnet run -- http://localhost:8080 b6b6f6b0-c251-4733-93c8-5587370baa42 PostgreSQL

The test harness exercises every SDK method and prints pass/fail for each. Exit code 0 means all tests passed. You can also use HNSWLITE_BASE_URL, HNSWLITE_API_KEY, and HNSWLITE_STORAGE_TYPE instead of positional arguments.

Target Frameworks

  • .NET 8.0
  • .NET 10.0
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 112 8/16/2026
2.0.1 122 6/18/2026
2.0.0 139 6/18/2026
1.2.0 132 4/17/2026
1.1.2 125 4/17/2026
1.1.1 121 4/16/2026
1.1.0 124 4/16/2026