Loading repository data…
Loading repository data…
tghamm / repository
An unofficial C#/.NET SDK for accessing the Anthropic Claude API. This package is not affiliated with, endorsed by, or sponsored by Anthropic. Anthropic and Claude are trademarks of Anthropic, PBC.
Anthropic.SDK is an unofficial C# client designed for interacting with the Claude AI API. This powerful interface simplifies the integration of the Claude AI into your C# applications. It targets NetStandard 2.0, .NET 8.0, and .NET 10.0.
Note: This package is not affiliated with, endorsed by, or sponsored by Anthropic. Anthropic and Claude are trademarks of Anthropic, PBC.
Install Anthropic.SDK via the NuGet package manager:
PM> Install-Package Anthropic.SDK
You can load the API Key from an environment variable named ANTHROPIC_API_KEY by default. Alternatively, you can supply it as a string to the AnthropicClient constructor.
The AnthropicClient can optionally take a custom HttpClient in the AnthropicClient constructor, which allows you to control elements such as retries and timeouts. Note: If you provide your own HttpClient, you are responsible for disposal of that client.
There are two ways to start using the AnthropicClient. The first is to simply new up an instance of the AnthropicClient and start using it, the second is to use the messaging client with Microsoft.SemanticKernel.
Brief examples of each are below.
Option 1:
var client = new AnthropicClient();
Option 2:
using Microsoft.SemanticKernel;
IChatClient CreateChatClient(IServiceProvider _)
=> new ChatClientBuilder(new AnthropicClient().Messages)
.UseFunctionInvocation()
.Build();
var sk = Kernel.CreateBuilder();
sk.Plugins.AddFromType<SkPlugins>("Weather");
sk.Services.AddSingleton(CreateChatClient);
See integration tests for a more complete example.
Here's an example of a non-streaming call to the Claude AI API to the Claude Sonnet 4.6 model:
var client = new AnthropicClient();
var messages = new List<Message>()
{
new Message(RoleType.User, "Who won the world series in 2020?"),
new Message(RoleType.Assistant, "The Los Angeles Dodgers won the World Series in 2020."),
new Message(RoleType.User, "Where was it played?"),
};
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 1024,
Model = AnthropicModels.Claude46Sonnet,
Stream = false,
Temperature = 1.0m,
};
var firstResult = await client.Messages.GetClaudeMessageAsync(parameters);
//print result
Console.WriteLine(firstResult.Message.ToString());
//print remaining Request Limit
Console.WriteLine(firstResult.RateLimits.RequestsLimit.ToString());
//add assistant message to chain for second call
messages.Add(firstResult.Message);
//ask followup question in chain
messages.Add(new Message(RoleType.User,"Who were the starting pitchers for the Dodgers?"));
var finalResult = await client.Messages.GetClaudeMessageAsync(parameters);
//print result
Console.WriteLine(finalResult.Message.ToString());
The following is an example of a streaming call to the Claude AI API Claude Opus 4.6 that provides an image for analysis:
string resourceName = "Anthropic.SDK.Tests.Red_Apple.jpg";
// Get the current assembly
Assembly assembly = Assembly.GetExecutingAssembly();
// Get a stream to the embedded resource
await using Stream stream = assembly.GetManifestResourceStream(resourceName);
// Read the stream into a byte array
byte[] imageBytes;
using (var memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
imageBytes = memoryStream.ToArray();
}
// Convert the byte array to a base64 string
string base64String = Convert.ToBase64String(imageBytes);
var client = new AnthropicClient();
var messages = new List<Message>();
messages.Add(new Message()
{
Role = RoleType.User,
Content = new List<ContentBase>()
{
new ImageContent()
{
Source = new ImageSource()
{
MediaType = "image/jpeg",
Data = base64String
}
},
new TextContent()
{
Text = "What is this a picture of?"
}
}
});
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 512,
Model = AnthropicModels.Claude46Opus,
Stream = true,
Temperature = 1.0m,
};
var outputs = new List<MessageResponse>();
await foreach (var res in client.Messages.StreamClaudeMessageAsync(parameters))
{
if (res.Delta != null)
{
Console.Write(res.Delta.Text);
}
outputs.Add(res);
}
Console.WriteLine(string.Empty);
Console.WriteLine($@"Used Tokens - Input:{outputs.First().StreamStartMessage.Usage.InputTokens}.
Output: {outputs.Last().Usage.OutputTokens}");
The AnthropicClient has support for the message token count endpoint. Below is an example of how to use it.
var client = new AnthropicClient();
var messages = new List<Message>();
messages.Add(new Message(RoleType.User, "Write me a sonnet about the Statue of Liberty"));
var parameters = new MessageCountTokenParameters
{
Messages = messages,
Model = AnthropicModels.Claude45Haiku
};
var response = await client.Messages.CountMessageTokensAsync(parameters);
Assert.IsTrue(res.InputTokens > 0);
The AnthropicClient has support for extended thinking in compatible models like Claude Opus 4.6 and Sonnet 4.6. Below is an example of how to use it. Streaming is supported similarly.
var client = new AnthropicClient();
var messages = new List<Message>();
messages.Add(new Message(RoleType.User, "How many r's are in the word strawberry?"));
var parameters = new MessageParameters()
{
Messages = messages,
MaxTokens = 4096,
Model = AnthropicModels.Claude46Sonnet,
Stream = false,
Temperature = 1.0m,
Thinking = new ThinkingParameters()
{
BudgetTokens = 4000
}
};
var res = await client.Messages.GetClaudeMessageAsync(parameters);
Assert.IsTrue(res.Content.OfType<ThinkingContent>().Any());
var response = res.Message.ToString();
var thoughts = res.Message.ThinkingContent;
Assert.IsNotNull(thoughts);
Assert.IsNotNull(response);
The AnthropicClient has support for the new IChatClient from Microsoft and offers a slightly different mechanism for using the AnthropicClient. Below are a few examples.
//function calling
IChatClient client = new AnthropicClient().Messages
.AsBuilder()
.UseFunctionInvocation()
.Build();
ChatOptions options = new()
{
ModelId = AnthropicModels.Claude45Haiku,
MaxOutputTokens = 512,
Tools = [AIFunctionFactory.Create((string personName) => personName switch {
"Alice" => "25",
_ => "40"
}, "GetPersonAge", "Gets the age of the person whose name is specified.")]
};
var res = await client.GetResponseAsync("How old is Alice?", options);
Assert.IsTrue(
res.Message.Text?.Contains("25") is true,
res.Message.Text);
//non-streaming
IChatClient client = new AnthropicClient().Messages;
ChatOptions options = new()
{
ModelId = AnthropicModels.Claude46Sonnet,
MaxOutputTokens = 512,
Temperature = 1.0f,
};
var res = await client.GetResponseAsync("Write a sonnet about the Statue of Liberty. The response must include the word green.", options);
Assert.IsTrue(res.Message.Text?.Contains("green") is true, res.Message.Text);
//streaming call
IChatClient client = new AnthropicClient().Messages;
ChatOptions options = new()
{
ModelId = AnthropicModels.Claude46Sonnet,
MaxOutputTokens = 512,
Temperature = 1.0f,
};
StringBuilder sb = new();
await foreach (var res in client.GetStreamingResponseAsync("Write a sonnet about the Statue of Liberty. The response must include the word green.", options))
{
sb.Append(res);
}
Assert.IsTrue(sb.ToString().Contains("green") is true, sb.ToString());
//Image call
string resourceName = "Anthropic.SDK.Tests.Red_Apple.jpg";
Assembly assembly = Assembly.GetExecutingAssembly();
await using Stream stream = assembly.GetManifestResourceStream(resourceName)!;
byte[] imageBytes;
using (var memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
imageBytes = memoryStream.ToArray();
}
IChatClient client = new AnthropicClient().Messages;
var res = await client.GetResponseAsync(
[
new ChatMessage(ChatRole.User,
[
new DataContent(imageBytes, "image/jpeg"),
new TextContent("What is this a picture of?"),
])
], new()
{
ModelId = AnthropicModels.Claude46Opus,
MaxOutputTokens = 512,
Temperature = 0f,
});
Assert.IsTrue(res.Message.Text?.Contains("apple", StringComparison.OrdinalIgnoreCase) is true, res.Message.Text);
Please see the unit tests for even more examples.
The IChatClient supports extended thinking through the ChatOptions extension methods. This provides a clean and fluent API for enabling thinking in compatible models like Claude Opus 4.6 and Sonnet 4.6:
using Anthropic.SDK.Extensions;
IChatClient client = new AnthropicClient().Messages;
List<ChatMessage> messages = new()
{
new ChatMessage(ChatRole.User, "How many r's are in the word strawberry?")
};
// Using the extension method for thinking parameters
ChatOptions options = new()
{
ModelId = AnthropicModels.Claude46Sonnet,
MaxOutputTokens = 4096,
Temperature = 1.0f,
}.WithThinking(4000); // Enable thinking with 4,000 budget tokens
var res = await client.GetResponseAsync(messages, options);
Console.WriteLine(res.Text); // The final answer
// Access thinking content if available
var thinkingContent = res.Message.Contents.OfType<TextReasoningContent>().FirstOrDefault();
if (thinkingContent != null)
{
Console.WriteLine("Claude's reasoning: " + thinkingContent.Text);
}
// Continue the conversation
messages.AddMessages(res);
messages.Add(new ChatMessage(ChatRole.User,