Skip to content

.NET SDK

The TruthVouch .NET SDK provides drop-in replacements for OpenAI, Anthropic, and Google AI providers. Fully integrated with .NET’s dependency injection system for automatic PII detection, policy enforcement, and hallucination detection.

Installation

Terminal window
dotnet add package TruthVouch.Sdk

Requires .NET 9.0+.


Quick Start

1. Register with Dependency Injection

In Program.cs:

builder.Services.AddTruthVouch(options =>
{
options.GatewayUrl = "https://gateway.truthvouch.com";
options.ApiKey = "tv_..."; // From TruthVouch dashboard → Settings → API Keys
options.FailMode = FailMode.Open; // Open = bypass on outage; Closed = block on outage
});

2. Inject and Use

public class MyService(ITruthVouchClient client)
{
public async Task<string> AskQuestionAsync(string question, CancellationToken ct)
{
var response = await client.Chat.CreateAsync(new ChatRequest
{
Model = "gpt-4o",
Messages = [new("user", question)]
}, ct);
// Governance metadata available on every response
if (response.Governance.Verdict == "blocked")
throw new GovernancePolicyViolationException(response.Governance);
if (response.Governance.PiiDetected)
_logger.LogWarning("PII detected in response");
return response.Content;
}
}

Provider Examples

OpenAI (drop-in replacement)

var response = await client.Chat.CreateAsync(new ChatRequest
{
Model = "gpt-4o",
Messages = [new("user", "Summarise this document")],
Temperature = 0.7,
MaxTokens = 1024
});
Console.WriteLine(response.Content);
Console.WriteLine($"Verdict: {response.Governance.Verdict}");
Console.WriteLine($"Overhead: {response.Governance.OverheadMs}ms");

Anthropic (drop-in replacement)

var response = await client.Messages.CreateAsync(new AnthropicMessageRequest
{
Model = "claude-3-5-sonnet-20241022",
MaxTokens = 1024,
System = "You are a helpful assistant.",
Messages = [new("user", "What is quantum computing?")]
});
Console.WriteLine(response.Content);

Google AI / Gemini (drop-in replacement)

var response = await client.Google.GenerateContentAsync(new GoogleContentRequest
{
Model = "gemini-1.5-pro",
Contents = [new("user", "Explain AI governance")]
});
Console.WriteLine(response.Text);

Streaming

await using var stream = await client.Chat.CreateStreamAsync(new ChatRequest
{
Model = "gpt-4o",
Messages = [new("user", "Write me a short story")]
});
await foreach (var chunk in stream.ReadChunksAsync(ct))
{
if (!string.IsNullOrEmpty(chunk.Content))
Console.Write(chunk.Content);
if (chunk.IsLast)
{
var gov = stream.GovernanceReport;
Console.WriteLine($"\nVerdict: {gov?.Verdict}");
}
}

Batch Scanning

Submit a document corpus for offline governance analysis:

var job = await client.Batch.SubmitAsync(new BatchScanRequest
{
SourceUrl = "s3://my-bucket/documents.jsonl",
Format = "jsonl",
ScanMode = "deep", // fast | standard | deep
CallbackUrl = "https://my-app.com/webhooks/scan-complete"
});
Console.WriteLine($"Job {job.Id} submitted — ETA: {job.EstimatedCompletion}");
// Poll for status
var status = await client.Batch.GetStatusAsync(job.Id);
Console.WriteLine($"Progress: {status.Scanned}/{status.Total} ({status.ProgressPercent}%)");
Console.WriteLine($"Flagged: {status.FlaggedCount}");

Circuit Breaker and Fail Modes

The SDK includes a built-in circuit breaker that opens after consecutive gateway failures.

FailModeBehavior
FailMode.Open (default)Bypass the gateway; call succeeds with governance.verdict = "bypassed"
FailMode.ClosedThrow GatewayUnreachableException; no LLM call is made
builder.Services.AddTruthVouch(options =>
{
options.FailMode = FailMode.Closed; // Compliance mode
options.CircuitBreakerFailureThreshold = 5; // Open after 5 failures
options.CircuitBreakerRecoverySeconds = 60; // Retry after 60 seconds
options.MaxRetries = 3; // Exponential backoff retries
});

Error Handling

try
{
var response = await client.Chat.CreateAsync(request);
}
catch (GovernancePolicyViolationException ex)
{
_logger.LogWarning("Blocked by governance: {Violations}",
string.Join(", ", ex.GovernanceReport!.PolicyViolations));
}
catch (TruthVouchAuthException ex)
{
_logger.LogError("Auth failed — check your API key. RequestId: {RequestId}", ex.RequestId);
}
catch (QuotaExceededException ex)
{
_logger.LogWarning("Rate limited. RetryAfter: {RetryAfter}", ex.RetryAfterUnixSeconds);
}
catch (TruthVouchException ex)
{
_logger.LogError("TruthVouch error [{Code}]: {Message}", ex.ErrorCode, ex.Message);
}

All SDK exceptions extend TruthVouchException and carry:

  • ErrorCode — standardised code string for programmatic handling
  • GovernanceReport — governance metadata when available
  • RequestId — for tracing with TruthVouch support

Configuration Reference

OptionTypeDefaultDescription
GatewayUrlstringrequiredTruthVouch Gateway base URL
ApiKeystringrequiredAPI key from TruthVouch dashboard
FailModeFailModeOpenBehaviour when gateway is unreachable
TimeoutSecondsint30HTTP request timeout
MaxRetriesint3Retry attempts (exponential backoff)
CircuitBreakerFailureThresholdint5Failures before circuit opens
CircuitBreakerRecoverySecondsint60Seconds until recovery probe
ServiceNamestring?nullOpenTelemetry service name for trace propagation

Verification API

Verify content independently of the gateway proxy — call the Trust API and data verification endpoints directly.

Verify Data Grounding

var result = await client.Verify.DataGroundingAsync(new DataGroundingRequest
{
Query = "What country had the highest uplift?",
Response = "Germany had the highest uplift at 23%.",
Sql = "SELECT country, uplift FROM sales ORDER BY uplift DESC",
RawResults = """[{"country": "France", "uplift": 0.181}]"""
});
Console.WriteLine($"Score: {result.OverallScore}"); // 0.15
Console.WriteLine($"Verdict: {result.Verdict}"); // "contradicted"
foreach (var claim in result.Claims)
Console.WriteLine($" {claim.Text}: {claim.Verdict} (score={claim.Score})");

Verify a Claim

var result = await client.Verify.ClaimAsync("Paris is the capital of France", mode: "standard");
Console.WriteLine($"Trust: {result.TrustScore}"); // 0.97
Console.WriteLine($"Verdict: {result.Verdict}"); // "accurate"

Check Faithfulness

var result = await client.Verify.FaithfulnessAsync(new FaithfulnessRequest
{
Response = "The project was completed in March 2026.",
Context = "The project wrapped up during March 2026 after 3 months of development.",
Strictness = "moderate"
});
Console.WriteLine($"Score: {result.Score}"); // 0.95
Console.WriteLine($"Faithful: {result.Faithful}"); // True

Evaluate Prompt Quality

var result = await client.Verify.PromptQualityAsync(
"You are a financial advisor who can access customer account balances and make transfers...");
Console.WriteLine($"Risk: {result.RiskLevel}"); // "high"
Console.WriteLine($"Issues: {string.Join(", ", result.Issues)}");

License

Apache-2.0


Next Steps