Plattform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modelle Tools & Services
Lösungen
Organisationen Entwickler Internet Service Provider Managed Service Provider AI-in-a-Box
Ressourcen
Support Documentation Blog Downloads
Unternehmen
Über uns Forschung Karriere Investieren Kontakt
Anmelden

.NET SDK

Official .NET client for ScaiGrid. Targets .NET 8 LTS. Idiomatic async/await throughout, with IAsyncEnumerable<ChatChunk> for streaming chat.

Install#

bash
1
dotnet add package ScaiLabs.ScaiGrid

Quickstart#

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
using ScaiLabs.ScaiGrid;
using ScaiLabs.ScaiGrid.Models;

using var client = ScaiGridClient.WithApiKey("sgk_...");

var models = await client.Models.ListAsync(modality: "chat");
foreach (var m in models)
{
    Console.WriteLine(m.GetProperty("slug").GetString());
}

var request = new ChatRequest
{
    Model = "anthropic/claude-haiku-4-5",
    Messages = new() { new() { Role = "user", Content = "Hello!" } },
    Metadata = new() { ["agentId"] = "..." },
};
await foreach (var chunk in client.Inference.ChatStreamAsync(request))
{
    Console.Write(chunk.Delta?.Content);
}
Console.WriteLine();

Authentication#

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 1. Static API key (most common)
using var client = ScaiGridClient.WithApiKey("sgk_...");

// 2. Pre-minted JWT
using var client = ScaiGridClient.WithBearerToken(jwt);

// 3. Custom IAuthProvider — implement OAuth client_credentials or
//    federated tokens yourself.
using var client = new ScaiGridClient(new ScaiGridClientOptions
{
    Auth = new MyAuthProvider(),
    BaseUrl = new Uri("https://scaigrid.example.com"),
});

The base interface is small:

csharp
1
2
3
4
public interface IAuthProvider
{
    ValueTask<string> GetHeaderAsync(CancellationToken cancellationToken = default);
}

Resources#

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Models
await client.Models.ListAsync(modality: "chat");
await client.Models.GetAsync("anthropic/claude-haiku-4-5");

// Inference — chat (Task), ChatStreamAsync (IAsyncEnumerable), embed
await client.Inference.ChatAsync(request);
await foreach (var chunk in client.Inference.ChatStreamAsync(request)) { }
await client.Inference.EmbedAsync(model: "...", input: new[] { "..." });

// Modules — generic proxy
await client.Modules.ProxyAsync(
    "scaimatrix", HttpMethod.Post, "/collections",
    jsonBody: new { name = "...", embedding_model = "..." });

Module sub-clients#

ScaiBot#

csharp
1
2
3
4
5
6
7
8
var bot = await client.ScaiBot.Bots.CreateAsync(
    name: "support",
    model: "anthropic/claude-haiku-4-5",
    displayName: "Support Bot");

var calls = await client.ScaiBot.Voice.ListCallsAsync(limit: 20);
var transcript = await client.ScaiBot.Voice.GetTranscriptAsync(callId);
var cost = await client.ScaiBot.Voice.GetCostAsync(callId);

ScaiSpeak#

csharp
1
2
3
4
5
6
var result = await client.ScaiSpeak.SynthesizeAsync(
    voiceId: "voice_...",
    text: "Hello, world!");
// result.Audio is a byte[] of decoded audio.

var voices = await client.ScaiSpeak.Voices.ListAsync(language: "nl");

ScaiDial#

csharp
1
2
3
4
5
6
7
8
var extensions = await client.ScaiDial.Extensions.ListAsync();
await client.ScaiDial.Extensions.CreateAsync(
    number: "1042", type: "bot", targetRef: bot.Id);

await client.ScaiDial.Dialplans.AddRuleAsync(
    dialplanId,
    actionType: "goto_extension",
    actionParams: new Dictionary<string, object?> { ["extension_number"] = "1042" });

Streaming#

ChatStreamAsync returns IAsyncEnumerable<ChatChunk>. Compose with await foreach and cancellation tokens:

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

await foreach (var chunk in client.Inference.ChatStreamAsync(request)
    .WithCancellation(cts.Token))
{
    Console.Write(chunk.Delta?.Content);
    if (chunk.FinishReason is not null)
    {
        Console.WriteLine($"  [finished: {chunk.FinishReason}]");
    }
}

Errors#

Every exception extends ScaiGridException with a Code mirroring the server:

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using ScaiLabs.ScaiGrid.Exceptions;

try
{
    await client.Inference.ChatAsync(request);
}
catch (RateLimitedException ex)
{
    Console.WriteLine($"retry after {ex.RetryAfter}");
}
catch (BudgetExceededException)
{
    // Tenant or user budget cap hit.
}
catch (ScaiGridException ex)
{
    // Catch-all; ex.Code, ex.HttpStatus, ex.RequestId all populated.
}

Full taxonomy: AuthException, AuthTokenInvalidException, AuthTokenExpiredException, PermissionDeniedException, NotFoundException, ConflictException, ValidationException, RateLimitedException, BudgetExceededException, BackendException, BackendTimeoutException, InternalServerException, TimeoutException, TransportException.

Request IDs + observability#

Every method takes an optional requestId. Forwarded as X-Request-ID:

csharp
1
2
3
await client.Inference.ChatAsync(
    request,
    requestId: "req-batch-job-7");

Dependency injection#

The client is IDisposable and safe to register as a singleton — the underlying HttpClient is reused across requests:

csharp
1
2
services.AddSingleton<ScaiGridClient>(_ => ScaiGridClient.WithApiKey(
    builder.Configuration["ScaiGrid:ApiKey"]!));

For tighter control, inject your own HttpClient (e.g. one from IHttpClientFactory with Polly handlers):

csharp
1
2
3
4
var http = httpClientFactory.CreateClient("scaigrid");
var client = new ScaiGridClient(
    new ScaiGridClientOptions { Auth = new ApiKeyAuth(apiKey) },
    http);

Download#

The current release is on /downloads under ScaiGrid → .NET, with SHA-256 verification.

See also#

Updated 2026-06-15 13:16:10 View source (.md) rev 2