.NET Integration with Keeptrusts
Keeptrusts exposes an OpenAI-compatible HTTP API. Any .NET HttpClient or library that targets the OpenAI REST contract can route through the gateway — no proprietary SDK required.
Use this page when
- You are connecting an ASP.NET or .NET application to the Keeptrusts gateway for policy-enforced AI calls.
- You need HttpClient, Semantic Kernel, or Polly patterns pointing at the gateway's OpenAI-compatible endpoint.
- You want to handle policy blocks (HTTP 409) gracefully in .NET error handling.
- You need health check integration with ASP.NET's
AddHealthChecks()for gateway connectivity.
Primary audience
- Primary: Technical Engineers
- Secondary: AI Agents, Technical Leaders
How it works
ASP.NET app
→ HttpClient / Semantic Kernel (base URI pointed at Keeptrusts)
→ kt gateway (policy evaluation)
→ upstream LLM provider
→ response (redacted / enriched per policy)
Prerequisites
- Keeptrusts CLI installed and a running gateway (
kt gateway run) - A valid gateway key (
kt_gk_...) - .NET 8+ SDK
HttpClient integration
Register a named HttpClient in Program.cs:
builder.Services.AddHttpClient("Keeptrusts", client =>
{
client.BaseAddress = new Uri("http://localhost:41002/v1/");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer",
builder.Configuration["Keeptrusts:GatewayKey"]);
});
Calling the completions endpoint
public class GovernedChatService
{
private readonly HttpClient _http;
public GovernedChatService(IHttpClientFactory factory)
{
_http = factory.CreateClient("Keeptrusts");
}
public async Task<string> CompleteAsync(string userMessage)
{
var body = new
{
model = "gpt-4o",
messages = new[] { new { role = "user", content = userMessage } }
};
var response = await _http.PostAsJsonAsync("chat/completions", body);
response.EnsureSuccessStatusCode();
var result = await response.Content
.ReadFromJsonAsync<JsonElement>();
return result
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString()!;
}
}
Semantic Kernel integration
Microsoft Semantic Kernel accepts a custom HttpClient, so the gateway slots in directly:
using Microsoft.SemanticKernel;
var httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:41002/v1/")
};
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
modelId: "gpt-4o",
apiKey: builder.Configuration["Keeptrusts:GatewayKey"]!,
httpClient: httpClient)
.Build();
var result = await kernel.InvokePromptAsync(
"Summarize our data retention policy.");
Console.WriteLine(result);
Using Semantic Kernel with DI
Register the kernel in the DI container:
builder.Services.AddSingleton(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var httpClient = new HttpClient
{
BaseAddress = new Uri(config["Keeptrusts:GatewayUrl"]!)
};
return Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
modelId: "gpt-4o",
apiKey: config["Keeptrusts:GatewayKey"]!,
httpClient: httpClient)
.Build();
});
ASP.NET middleware for governance headers
Add middleware that forwards governance metadata from gateway responses:
public class GovernanceHeaderMiddleware
{
private readonly RequestDelegate _next;
public GovernanceHeaderMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
await _next(context);
if (context.Items.TryGetValue("GovernanceEventId", out var eventId))
{
context.Response.Headers.Append(
"X-Governance-Event-Id", eventId?.ToString());
}
}
}
Register it in Program.cs:
app.UseMiddleware<GovernanceHeaderMiddleware>();
Polly retry policies
Use Polly to retry on transient failures (429, 5xx) while letting policy blocks (409) propagate:
builder.Services.AddHttpClient("Keeptrusts", client =>
{
client.BaseAddress = new Uri("http://localhost:41002/v1/");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer",
builder.Configuration["Keeptrusts:GatewayKey"]);
})
.AddPolicyHandler(Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.OrResult(r =>
r.StatusCode == HttpStatusCode.TooManyRequests ||
(int)r.StatusCode >= 500)
.WaitAndRetryAsync(3,
attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt))));
Policy blocks (409) are not retried — they indicate a governance decision, not a transient fault.
Error handling
public async Task<string> SafeCompleteAsync(string message)
{
var body = new
{
model = "gpt-4o",
messages = new[] { new { role = "user", content = message } }
};
var response = await _http.PostAsJsonAsync("chat/completions", body);
if (response.StatusCode == HttpStatusCode.Conflict) // 409
{
var detail = await response.Content.ReadAsStringAsync();
throw new GovernancePolicyException(detail);
}
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<JsonElement>();
return result
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString()!;
}
public class GovernancePolicyException : Exception
{
public GovernancePolicyException(string detail)
: base($"Request blocked by governance policy: {detail}") { }
}
Health check
Add a gateway health check for ASP.NET health monitoring:
builder.Services.AddHealthChecks()
.AddUrlGroup(
new Uri("http://localhost:41002/v1/models"),
name: "keeptrusts-gateway",
timeout: TimeSpan.FromSeconds(3));
Access the health endpoint at /healthz to verify gateway connectivity.
Configuration via appsettings.json
{
"Keeptrusts": {
"GatewayUrl": "http://localhost:41002/v1/",
"GatewayKey": "kt_gk_your_gateway_key"
}
}
Override with environment variables in production:
export Keeptrusts__GatewayUrl=https://gateway.example.com/v1/
export Keeptrusts__GatewayKey=kt_gk_production_key
Validating your policy config
kt policy lint --file policy-config.yaml
Tailing governance events
kt events tail --follow
Summary
| Pattern | Key change |
|---|---|
| HttpClient | Set BaseAddress to gateway URL |
| Semantic Kernel | Pass custom HttpClient to builder |
| Polly | Retry 429 / 5xx, skip 409 |
| Health check | AddUrlGroup targeting /v1/models |
| ASP.NET middleware | Forward governance headers |
| Error handling | Catch 409 for policy blocks |
For AI systems
- Canonical terms: Keeptrusts gateway, gateway key (
kt_gk_...), OpenAI-compatible API,HttpClient, Microsoft Semantic Kernel, Polly retry policy, HTTP 409 policy block. - Key config:
BaseAddress=http://localhost:41002/v1/,Authorization: Bearer kt_gk_...,appsettings.jsonsectionKeeptrusts:GatewayUrlandKeeptrusts:GatewayKey. - CLI commands:
kt gateway run,kt policy lint,kt events tail --follow. - Best next pages: Python SDK patterns, Node.js SDK patterns, Java & Spring Boot.
For engineers
- Prerequisites: .NET 8+ SDK, running Keeptrusts gateway (
kt gateway run), a gateway key from the console. - Validate:
curl http://localhost:41002/v1/modelsreturns model list. Health check at/healthzconfirms ASP.NET can reach the gateway. - Key pattern: Retry 429/5xx with Polly exponential backoff; never retry 409 (policy block is intentional).
- Production override: Set
Keeptrusts__GatewayUrlandKeeptrusts__GatewayKeyenvironment variables to overrideappsettings.json.
For leaders
- No SDK lock-in: Uses standard
HttpClientandSemantic Kernel— no proprietary Keeptrusts NuGet package required. - Governance transparency: Every AI call passes through the gateway; policy blocks return 409 with structured reasons for audit.
- Adoption path: Change one URL (
BaseAddress) to route existing OpenAI integrations through governance. - Resilience: Polly handles transient failures without masking governance decisions.
Next steps
- Python SDK patterns for Python-based services
- Node.js SDK patterns for TypeScript/JavaScript services
- Deploy the gateway on Kubernetes for production hosting
- CI/CD pipeline integration for automated policy validation