Every major AI provider has a proper .NET SDK.
OpenAI has one. Azure OpenAI has one. Even smaller providers have community SDKs.
But Anthropic's Claude — arguably one of the most capable AI models available right now — had nothing. Just developers hand-rolling HttpClient wrappers, copy-pasting JSON serialization code, and reinventing retry logic across every project.
So I built ClaudeAI.DotNet — an enterprise-grade .NET 8 SDK that makes Claude feel like a first-class citizen in the .NET ecosystem.
And as of today, it's live on NuGet. 🎉
dotnet add package ClaudeAI.DotNet
🤔 Why Did This Need to Exist?
Here's what integrating Claude looked like before this SDK:
// The painful way — what everyone was doing
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("anthropic-version", "2023-06-01");
var payload = new
{
model = "claude-sonnet-4-5",
max_tokens = 1024,
messages = new[] { new { role = "user", content = prompt } }
};
var json = JsonSerializer.Serialize(payload);
var response = await client.PostAsync(
"https://api.anthropic.com/v1/messages",
new StringContent(json, Encoding.UTF8, "application/json"));
var result = await response.Content.ReadAsStringAsync();
// Now parse the JSON manually... 😩
No DI support. No retry logic. No streaming abstractions. No structure whatsoever.
Here's what it looks like with ClaudeAI.DotNet:
// The clean way
builder.Services.AddClaudeAI(options =>
{
options.ApiKey = config["Claude:ApiKey"];
options.Model = ClaudeModel.Sonnet;
});
// In your service
public async Task<string> AskAsync(string question)
=> await _claude.SendAsync(question);
🏗️ Architecture
The SDK is built on a clean 8-layer architecture:
ClaudeAI.DotNet/
├── Configuration/ ← ClaudeOptions, ClaudeModel constants
├── Models/ ← Request, Response, Message, StreamChunk DTOs
├── Core/ ← HTTP pipeline, retry logic, SSE streaming
├── Skills/ ← ISkill, BaseSkill, built-in skill library
├── Commands/ ← ClaudeCommand, ClaudeCommandResult (CQRS)
├── Tools/ ← [ClaudeTool] attribute, ToolRegistry
├── Services/ ← IClaudeClient, ClaudeClient, RequestBuilder
└── Extensions/ ← AddClaudeAI(), ClaudeAIBuilder (DI)
Each layer has a single responsibility. The AI layer is completely isolated from your business logic — meaning you could swap Claude for another provider with minimal changes.
🎯 Key Features
1. Fluent DI Registration
One-line setup that integrates naturally with ASP.NET Core:
builder.Services.AddClaudeAI(options =>
{
options.ApiKey = builder.Configuration["Claude:ApiKey"];
options.Model = ClaudeModel.Sonnet; // or ClaudeModel.Opus
options.MaxTokens = 4096;
options.SystemPrompt = "You are a helpful assistant.";
})
.WithSkill<SummarizationSkill>()
.WithSkill<CodeReviewSkill>()
.WithTools<MyWeatherTools>();
Or bind directly from appsettings.json:
builder.Services.AddClaudeAI(builder.Configuration);
{
"Claude": {
"ApiKey": "your-key-here",
"Model": "claude-sonnet-4-5",
"MaxTokens": 4096
}
}
2. Built-in Skills System
The Skills system is the most novel part of the SDK. A Skill is a reusable module that encapsulates a system prompt and optional prompt transformation — letting you standardize AI behaviour across your application.
// Use built-in skills
var summary = await _claude.SendWithSkillAsync(longText, new SummarizationSkill());
var review = await _claude.SendWithSkillAsync(myCode, new CodeReviewSkill());
var french = await _claude.SendWithSkillAsync(text, new TranslationSkill("French"));
var sentiment = await _claude.SendWithSkillAsync(feedback, new SentimentAnalysisSkill());
Built-in skills included:
| Skill | What it does |
|---|---|
SummarizationSkill |
Concise, structured summaries |
CodeReviewSkill |
Detailed review with ratings |
TranslationSkill |
Translate to any language |
SentimentAnalysisSkill |
Returns structured JSON sentiment |
DocumentationSkill |
Generates XML doc comments |
Building a custom skill is trivial:
public class GrammarCorrectionSkill : BaseSkill
{
public override string Name => "GrammarCorrection";
public override string GetSystemPrompt() =>
"""
You are an expert editor. Correct grammar, spelling, and punctuation.
Preserve the author's voice. Return only the corrected text.
""";
public override string TransformPrompt(string userPrompt) =>
$"Please correct the following:\n\n{userPrompt}";
}
// Register and use it
builder.Services.AddClaudeAI(opt => ...)
.WithSkill<GrammarCorrectionSkill>();
var corrected = await _claude.SendWithSkillAsync(draftText, new GrammarCorrectionSkill());
3. Real Streaming Support
Full SSE (Server-Sent Events) streaming via IAsyncEnumerable<StreamChunk>:
await foreach (var chunk in _claude.StreamAsync("Write a blog post about .NET 8"))
{
if (!chunk.IsFinal)
Console.Write(chunk.Delta); // tokens arrive in real-time
}
Works perfectly with SignalR for real-time UIs, or just terminal output.
4. Multi-turn Conversations
var history = new List<ClaudeMessage>
{
ClaudeMessage.User("My name is Shatrughna and I work as a Software Developer."),
ClaudeMessage.Assistant("Nice to meet you!"),
ClaudeMessage.User("What kind of engineering challenges might I face?")
};
var reply = await _claude.ChatAsync(history);
5. CQRS Command Pattern
Perfect for teams already using MediatR or clean architecture:
var result = await _claude.ExecuteAsync(new ClaudeCommand
{
Prompt = "Analyze this customer review...",
Skill = new SentimentAnalysisSkill(),
MaxTokensOverride = 256,
ModelOverride = ClaudeModel.Opus // use a stronger model just for this command
});
if (result.IsSuccess)
{
Console.WriteLine(result.Content);
Console.WriteLine($"Model : {result.Model}");
Console.WriteLine($"Tokens : {result.Usage?.TotalTokens}");
Console.WriteLine($"Skill : {result.SkillUsed}");
}
else
{
_logger.LogError("Claude failed: {Error}", result.ErrorMessage);
}
6. Function Calling with [ClaudeTool]
Attribute-based tool registration — Claude can call your methods directly:
public class MyTools
{
[ClaudeTool("get_stock_price", "Returns the current stock price for a ticker symbol")]
public async Task<string> GetStockPriceAsync(string ticker)
{
var price = await _stockApi.GetPriceAsync(ticker);
return $"{ticker}: ${price}";
}
[ClaudeTool("get_weather", "Returns current weather for a city")]
public async Task<string> GetWeatherAsync(string city)
{
return await _weatherService.GetCurrentAsync(city);
}
}
// Register
builder.Services.AddClaudeAI(opt => opt.ApiKey = "...")
.WithTools<MyTools>();
7. Fluent Per-Request Builder
When you want to override behaviour for a single request:
var result = await _claude
.With()
.Skill<CodeReviewSkill>()
.SendAsync(mySourceCode);
🔄 Retry & Resilience
Built-in exponential backoff retry — configured via options:
options.MaxRetries = 3; // retry up to 3 times
options.TimeoutSeconds = 120; // 2 minute timeout
On transient HTTP failures, the SDK automatically retries with delays of 2s, 4s, 8s before giving up.
✅ Testing
The SDK is designed for testability. IClaudeClient is a proper interface — easy to mock in unit tests:
var mockClaude = new Mock<IClaudeClient>();
mockClaude
.Setup(x => x.SendAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync("Mocked response");
var service = new MyService(mockClaude.Object);
var result = await service.ProcessAsync("test input");
result.Should().NotBeNullOrEmpty();
🚀 Getting Started in 2 Minutes
dotnet add package ClaudeAI.DotNet
// Program.cs
builder.Services.AddClaudeAI(opt =>
{
opt.ApiKey = builder.Configuration["Claude:ApiKey"];
});
// YourService.cs
public class YourService
{
private readonly IClaudeClient _claude;
public YourService(IClaudeClient claude) => _claude = claude;
public async Task<string> SummarizeAsync(string text)
=> await _claude.SendWithSkillAsync(text, new SummarizationSkill());
}
That's literally it.
📦 What's Next
Here's the roadmap I'm working toward:
- [ ] Agent workflows — multi-step autonomous task execution
- [ ] Prompt template versioning
- [ ] RAG (Retrieval-Augmented Generation) skill
- [ ] Embeddings support
- [ ] Azure Functions integration
- [ ] Source generator for automatic tool binding
- [ ] OpenTelemetry tracing + token usage metrics
- [ ]
ClaudeAI.DotNet.MediatRintegration package
🔗 Links
- 📦 NuGet: https://www.nuget.org/packages/ClaudeAI.DotNet
- ⭐ GitHub: https://github.com/shatru123/claude-ai-dotnet-sdk
- 🐛 Issues: https://github.com/shatru123/claude-ai-dotnet-sdk/issues
If this SDK saves you time or solves a real problem for you — a ⭐ on GitHub goes a long way for an open source maintainer. And if you find a bug or want a feature, PRs are very welcome!
Happy to answer any questions about the architecture or design decisions in the comments. 👇
Built with ❤️ by Shatrughna | Pune, India 🇮🇳
Top comments (0)