Skip to content

cortexiumlabs/vectra-sdk-dotnet

Vectra SDK for .NET

NuGet License: Apache-2.0 .NET 10

Official .NET client library for Vectra — the Intent-Aware Governance Gateway for Autonomous AI Agents.

Vectra sits between your AI agents and the outside world, enforcing governance policies, intercepting high-risk actions, and routing requests through Human-in-the-Loop (HITL) review when needed. This SDK gives your .NET applications strongly-typed access to every capability Vectra exposes: agent registration, JWT authentication, policy inspection, and HITL review workflows.

Table of Contents

Features

  • Agent Management — Register, list, assign policies to, and delete AI agents.
  • JWT Authentication — Exchange agent credentials for a scoped Bearer token with one call.
  • Policy Inspection — List and inspect the governance policies configured in your gateway.
  • HITL Review Workflows — Retrieve pending review requests, then approve or deny them programmatically.
  • First-class DI support — Single AddVectraClient(...) extension wires up all typed HTTP clients.
  • Automatic Bearer token injection — Set BearerToken once; every outgoing request carries the header.
  • Structured exceptionsVectraApiException and VectraAuthenticationException expose the HTTP status code and the server's error payload.
  • Full cancellation support — Every async method accepts a CancellationToken.
  • Pagination — All list operations accept page and pageSize parameters.

Prerequisites

Requirement Version
.NET 10.0+
Vectra Gateway Running and reachable (default: http://localhost:7080)

Installation

dotnet add package Vectra.Client.Net

Or via the NuGet Package Manager:

Install-Package Vectra.Client.Net

Quick Start

// Program.cs — ASP.NET Core / Generic Host
builder.Services.AddVectraClient(options =>
{
    options.BaseUrl     = "http://localhost:7080";
    options.BearerToken = "your-jwt-token"; // optional; see Token Authentication
});
// Any service that needs Vectra
public class MyService(IVectraClient vectra)
{
    public async Task RunAsync(CancellationToken ct)
    {
        // List registered agents
        var agents = await vectra.Agents.ListAsync(page: 1, pageSize: 10, ct);
        foreach (var agent in agents)
            Console.WriteLine($"[{agent.Status,-8}] {agent.Name}  id={agent.AgentId}");

        // List governance policies
        var policies = await vectra.Policies.ListAsync(cancellationToken: ct);
        foreach (var policy in policies)
            Console.WriteLine($"{policy.PolicyName}  owner={policy.Owner}");

        // Check the HITL queue
        var pending = await vectra.Hitl.GetAllPendingAsync(cancellationToken: ct);
        Console.WriteLine($"Pending HITL reviews: {pending.Count}");
    }
}

Configuration

Register the SDK with AddVectraClient and supply a configuration delegate:

builder.Services.AddVectraClient(options =>
{
    options.BaseUrl     = "http://localhost:7080"; // required
    options.BearerToken = "<jwt>";                 // optional — injected on every request
    options.Timeout     = TimeSpan.FromSeconds(30);// default: 30 s
    options.ThrowOnError = true;                   // default: true
});

You can also pass a pre-built VectraClientOptions instance (useful when binding from appsettings.json):

var opts = builder.Configuration
    .GetSection("Vectra")
    .Get<VectraClientOptions>()!;

builder.Services.AddVectraClient(opts);

VectraClientOptions Properties

Property Type Default Description
BaseUrl string (required) Base URL of the Vectra gateway.
BearerToken string? null Static JWT injected as Authorization: Bearer <token>.
Timeout TimeSpan 00:00:30 Per-request HTTP timeout.
ThrowOnError bool true Throw VectraApiException on non-2xx responses.

API Reference

All operations are accessed through the IVectraClient facade:

IVectraClient
├── .Agents    → IVectraAgentClient
├── .Policies  → IVectraPolicyClient
├── .Hitl      → IVectraHitlClient
└── .Tokens    → IVectraTokenClient

Agent Management

// List agents (paginated)
IReadOnlyList<AgentSummary> agents = await vectra.Agents.ListAsync(page: 1, pageSize: 25, ct);

// Register a new agent
RegisterAgentResult result = await vectra.Agents.RegisterAsync(new RegisterAgentRequest
{
    Name         = "my-research-agent",
    OwnerId      = "team-backend",
    ClientSecret = "super-secret-value"   // store securely — Vectra hashes it
}, ct);

Console.WriteLine($"New agent ID: {result.AgentId}");

// Assign a policy to an agent
await vectra.Agents.AssignPolicyAsync(result.AgentId, new AssignPolicyRequest
{
    PolicyName = "strict-outbound"
}, ct);

// Delete an agent
await vectra.Agents.DeleteAsync(result.AgentId, ct);

AgentSummary Properties

Property Type Description
AgentId Guid Unique identifier.
Name string Display name.
Status AgentStatus Current lifecycle status (e.g. Active, Inactive).
PolicyName string? Name of the assigned policy, or null.

Token Authentication

Exchange an agent's credentials for a scoped JWT:

GenerateTokenResult token = await vectra.Tokens.GenerateAsync(new GenerateTokenRequest
{
    AgentId      = agentId,
    ClientSecret = "super-secret-value"
}, ct);

// Apply the token to all subsequent SDK calls
optionsMonitor.CurrentValue.BearerToken = token.AccessToken;

Token Refresh Pattern

public sealed class TokenRefresher(
    IVectraClient vectra,
    IOptionsMonitor<VectraClientOptions> options,
    Guid agentId,
    string clientSecret)
{
    private readonly SemaphoreSlim _lock = new(1, 1);
    private DateTime _expiresAt;

    public async Task EnsureValidTokenAsync(CancellationToken ct = default)
    {
        if (DateTime.UtcNow < _expiresAt) return;

        await _lock.WaitAsync(ct);
        try
        {
            if (DateTime.UtcNow >= _expiresAt)
            {
                var result = await vectra.Tokens.GenerateAsync(
                    new GenerateTokenRequest { AgentId = agentId, ClientSecret = clientSecret }, ct);

                options.CurrentValue.BearerToken = result.AccessToken;
                _expiresAt = DateTime.UtcNow.AddMinutes(55); // refresh before expiry
            }
        }
        finally { _lock.Release(); }
    }
}

Policy Inspection

// List all policies (paginated)
IReadOnlyList<PolicySummary> policies = await vectra.Policies.ListAsync(page: 1, pageSize: 25, ct);

// Get full policy details including rules
PolicyDetails details = await vectra.Policies.GetAsync("strict-outbound", ct);

Console.WriteLine($"Policy : {details.Name}");
Console.WriteLine($"Default: {details.Default}");
foreach (var rule in details.Rules)
    Console.WriteLine($"  [{rule.Effect}] {rule.Description}");

PolicyDetails Properties

Property Type Description
Name string Policy identifier.
Description string? Human-readable description.
Owner string Team or user that owns this policy.
Default PolicyType Effect applied when no rule matches.
Rules IReadOnlyList<PolicyRule> Ordered list of evaluation rules.
CreatedOn DateTime? Creation timestamp.

Human-in-the-Loop (HITL)

When Vectra intercepts a high-risk agent request it raises a HITL item. Your operators (or automation) can then approve or deny the item, controlling whether the original request is replayed upstream.

// 1. Get the queue of pending reviews
IReadOnlyList<PendingHitlRequest> queue =
    await vectra.Hitl.GetAllPendingAsync(page: 1, pageSize: 25, ct);

// 2. Inspect a specific item
HitlStatusResponse status = await vectra.Hitl.GetStatusAsync(queue[0].Id, ct);
Console.WriteLine($"Status : {status.Status}");
Console.WriteLine($"Method : {status.Method}  URL: {status.Url}");
Console.WriteLine($"Reason : {status.Reason}");

// 3. Approve — gateway replays the request to the upstream service
await vectra.Hitl.ApproveAsync(queue[0].Id, new ReviewDecisionRequest
{
    Comment = "Verified safe by on-call engineer."
}, ct);

// 4. Deny — gateway permanently blocks the request
await vectra.Hitl.DenyAsync(queue[0].Id, new ReviewDecisionRequest
{
    Comment = "Blocked: unexpected data-exfiltration attempt."
}, ct);

PendingHitlRequest Properties

Property Type Description
Id string Unique identifier of the HITL item.
Method string HTTP method of the intercepted request.
Url string Target URL of the intercepted request.
Reason string Gateway's classification reason for interception.
CreatedAt DateTime When the item entered the queue.

Error Handling

The SDK uses a structured exception hierarchy:

VectraException                    (base — all SDK errors)
├── VectraApiException             (non-2xx HTTP response)
└── VectraAuthenticationException  (401 / 403 responses)
try
{
    var policy = await vectra.Policies.GetAsync("unknown-policy", ct);
}
catch (VectraAuthenticationException ex)
{
    // 401 or 403 — re-authenticate or surface to the user
    Console.WriteLine($"Auth error [{ex.StatusCode}]: {ex.Message}");
}
catch (VectraApiException ex) when (ex.StatusCode == 404)
{
    Console.WriteLine("Policy not found.");
}
catch (VectraApiException ex)
{
    // All other non-2xx responses
    Console.WriteLine($"API error [{ex.StatusCode}]: {ex.Message}");

    // Structured payload from the server (when available)
    if (ex.ApiError is { } err)
        Console.WriteLine($"Server detail: {err.Detail}");
}
catch (VectraException ex)
{
    // SDK-level error (e.g. serialization, configuration)
    Console.WriteLine($"SDK error: {ex.Message}");
}
catch (OperationCanceledException)
{
    Console.WriteLine("Request timed out or was cancelled.");
}

Set options.ThrowOnError = false to suppress automatic exception throwing and handle HTTP errors manually via status codes.

Dependency Injection

The SDK integrates with Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Http.

ASP.NET Core / Generic Host

// Program.cs
builder.Services.AddVectraClient(options =>
{
    options.BaseUrl     = builder.Configuration["Vectra:BaseUrl"]!;
    options.BearerToken = builder.Configuration["Vectra:BearerToken"];
});
// Inject into any service
public class AgentOrchestrator(IVectraClient vectra) { ... }

Console Application (manual ServiceCollection)

var services = new ServiceCollection();
services.AddVectraClient(opts =>
{
    opts.BaseUrl     = "http://localhost:7080";
    opts.BearerToken = "<jwt>";
});

await using var provider = services.BuildServiceProvider();
var vectra = provider.GetRequiredService<IVectraClient>();

Registered Services

Interface Implementation Lifetime
IVectraClient VectraClient Transient
IVectraAgentClient AgentClient Typed HttpClient
IVectraPolicyClient PolicyClient Typed HttpClient
IVectraHitlClient HitlClient Typed HttpClient
IVectraTokenClient TokenClient Typed HttpClient

Advanced Usage

Per-Request Timeout via CancellationToken

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var agents = await vectra.Agents.ListAsync(cancellationToken: cts.Token);

Reacting to Option Changes

optionsMonitor.OnChange(opts =>
{
    logger.LogInformation("Vectra BearerToken rotated at {Time}", DateTimeOffset.UtcNow);
});

Background HITL Monitor

Poll the HITL queue on a timer and auto-approve safe requests:

public class HitlMonitorService(IVectraClient vectra, ILogger<HitlMonitorService> logger)
    : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var pending = await vectra.Hitl.GetAllPendingAsync(cancellationToken: stoppingToken);

            foreach (var request in pending)
            {
                // Apply your own approval logic here
                logger.LogInformation("Pending HITL: {Id} — {Method} {Url}", request.Id, request.Method, request.Url);
            }

            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
}

Running the Examples

The examples/ project contains ten annotated runnable examples covering every SDK feature:

# Name What it demonstrates
01 Quick Start List agents, policies, and HITL queue in a few lines
02 Token Authentication Credential exchange, token refresh, auth error handling
03 Agent Management Register, list, assign policy, delete agents
04 Policy Inspection List policies, drill into rules
05 HITL Workflow Pending queue, status inspection, approve/deny
06 Error Handling All exception types, when-clause patterns
07 Background HITL Monitor Polling queue as a hosted background service
08 Agent Lifecycle Full create → configure → decommission flow
09 Advanced Configuration Runtime options, manual DI, per-request timeouts
10 Pagination & Bulk Iterating large result sets efficiently
# Make sure the Vectra gateway is running first
cd examples
dotnet run

Edit examples/Program.cs to configure the gateway URL, Bearer token, and which example to execute.

Running the Tests

dotnet test tests/Vectra.Client.UnitTests

The test suite uses xUnit and covers all HTTP clients, the DI extensions, exception types, model validation, and internal helpers via mock HTTP message handlers — no live gateway required.

Contributing

  1. Fork the repository and create a feature branch.
  2. Add or update tests for any changed behaviour.
  3. Ensure dotnet build and dotnet test both pass.
  4. Open a pull request against main.

Please follow the existing code style (nullable reference types enabled, required properties, XML doc comments on public API).

License

© Cortexium Labs. Licensed under the Apache License, Version 2.0.

About

.NET client library for Vectra – Intent-Aware Governance Gateway for Autonomous AI Agents. Simplifies agent registration, JWT auth, proxy calls, and Human‑in‑the‑Loop (HITL) approvals.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages