ROAM .NET SDK

Async-first .NET 8 client library for the Object Agent Mapper (ROAM). Install via NuGet:

dotnet add package RoamSdk

Quick Start

using Roam.Sdk;

var config = new RoamClientConfig
{
    Host = "localhost",
    Port = 50051,
    ApiKey = "your-api-key"
};

await using var client = new RoamClient(config);
await client.ConnectAsync();

var sessionId = await client.RegisterAsync("my-agent", "1.0.0", SchemaMode.CodeFirst);
await client.RegisterModelAsync("users");
await client.CloseAsync();

RoamClientConfig

PropertyTypeDefaultDescription
Hoststring"localhost"Backend hostname
Portint50051gRPC port
ApiKeystringrequiredInjected as x-roam-api-key interceptor
UseTlsboolfalseUse HTTPS/TLS channel

RoamClient

Main entry point. Implements IAsyncDisposable and IDisposable.

Properties

PropertyTypeDescription
IsConnectedboolTrue when channel is open
SchemaModeSchemaModeCurrent schema mode set by RegisterAsync
RegisteredModelsIReadOnlyCollection<string>Registered table names
QueryQueryExecutorSQL query executor (requires connection)

ConnectAsync() / Connect()

Opens the gRPC channel and initialises Agent, Query, and Schema service clients.

await client.ConnectAsync();

RegisterAsync(agentId, version, mode) / Register()

Registers the agent and returns the session ID string.

var sessionId = await client.RegisterAsync("my-agent", "1.0.0", SchemaMode.CodeFirst);

RegisterModelAsync(tableName) / RegisterModel()

Registers a table name for agent access. Only allowed in CodeFirst and Hybrid modes.

await client.RegisterModelAsync("orders");

CloseAsync() / Close()

Gracefully shuts down the channel and cleans up resources.

SchemaMode Enum

public enum SchemaMode
{
    DataFirst = 0,  // Read-only. Schema from DB introspection. Model registration not allowed.
    CodeFirst = 1,  // App extension. Only registered models. Read-write capable.
    Hybrid    = 2,  // Registered models + read-only introspection fallback.
}

Entity Framework Core Integration

Decorate EF Core models with [RoamModel] and extend RoamDbContext:

using Roam.Sdk.ORM;
using Microsoft.EntityFrameworkCore;

[RoamModel("users")]
public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public string Email { get; set; } = "";
}

public class MyDbContext : RoamDbContext
{
    public DbSet<User> Users => Set<User>();

    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlServer("connection-string");
}

Exception Hierarchy

ExceptionWhen thrown
AuthenticationExceptionInvalid API key or connection failure
SchemaModeMismatchExceptionRegisterModel called in DataFirst mode
ValidationExceptionClient-side SQL validation failure
RoamExceptionBase class for all ROAM-specific errors

Dependency Injection

services.AddSingleton(new RoamClientConfig
{
    Host = "localhost",
    Port = 50051,
    ApiKey = Environment.GetEnvironmentVariable("ROAM_API_KEY")!
});
services.AddSingleton<RoamClient>();

Testing with TestClient

Roam.Sdk.Testing.TestClient is an in-memory stub that implements the same interface as RoamClient — no backend required.

using Roam.Sdk.Testing;

var client = new TestClient();
await client.RegisterModelAsync("users");
Assert.Contains("users", client.RegisteredModels);

Building & Testing

# Build
dotnet build

# Unit tests (no backend needed)
dotnet test tests/unit/RoamSdk.Tests.csproj

# Integration tests (requires make grpc-start)
dotnet test tests/integration/RoamSdk.IntegrationTests.csproj