### Get Started with Claude SDK for C# Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/README.md Basic example demonstrating how to initialize the client, create message parameters, and send a message to Claude. Ensure you have the necessary using statements. ```csharp using System; using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); MessageCreateParams parameters = new() { MaxTokens = 1024, Messages = [ new() { Role = Role.User, Content = "Hello, Claude", }, ], Model = "claude-opus-4-6", }; var message = await client.Messages.Create(parameters); Console.WriteLine(message); ``` -------------------------------- ### Bootstrap and Build SDK Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/CONTRIBUTING.md Run these commands to install dependencies and build the SDK. ```sh ./scripts/bootstrap ./scripts/build ``` -------------------------------- ### Install Claude SDK for C# Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/README.md Use this command to add the official Claude SDK package to your C# project. ```bash dotnet add package Anthropic ``` -------------------------------- ### Create and Manage Managed Agents and Sessions in C# Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use this snippet to create a persistent workspace (environment), define an agent with specific tools and models, and initiate a live conversation (session). It also shows how to send user messages and stream responses until the session is idle. Ensure you have the necessary Anthropic SDK packages installed. ```csharp using Anthropic; using Anthropic.Models.Beta.Agents; using Anthropic.Models.Beta.Environments; using Anthropic.Models.Beta.Sessions; using Anthropic.Models.Beta.Sessions.Events; AnthropicClient client = new(); // 1. Create an environment (persistent workspace) var environment = await client.Beta.Environments.Create( new EnvironmentCreateParams { Name = "my-environment" }); // 2. Create an agent with the built-in toolset var agent = await client.Beta.Agents.Create(new AgentCreateParams { Name = "my-agent", Model = BetaManagedAgentsModel.ClaudeSonnet4_6, System = "You are a helpful assistant.", Tools = [ new BetaManagedAgentsAgentToolset20260401Params { Type = BetaManagedAgentsAgentToolset20260401ParamsType.AgentToolset20260401, DefaultConfig = new BetaManagedAgentsAgentToolsetDefaultConfigParams { Enabled = true, PermissionPolicy = new BetaManagedAgentsAlwaysAllowPolicy { Type = BetaManagedAgentsAlwaysAllowPolicyType.AlwaysAllow, }, }, }, ], }); // 3. Create a session bound to the agent and environment var session = await client.Beta.Sessions.Create(new SessionCreateParams { Agent = agent.ID, EnvironmentID = environment.ID, }); // 4. Send a user message await client.Beta.Sessions.Events.Send(session.ID, new EventSendParams { Events = [ new BetaManagedAgentsUserMessageEventParams { Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage, Content = [new BetaManagedAgentsTextBlock { Type = BetaManagedAgentsTextBlockType.Text, Text = "Hello! What tools do you have access to?", }], }, ], }); // 5. Stream events until the session goes idle await foreach (var evt in client.Beta.Sessions.Events.StreamStreaming(session.ID)) { Console.WriteLine(evt); if (evt.TryPickSessionStatusIdleEvent(out _)) break; } ``` -------------------------------- ### Handle Anthropic SDK Exceptions in C# Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use a try-catch block to handle specific Anthropic API exceptions. This example shows how to catch unauthorized, rate limit, bad request, not found, server, and I/O errors. Ensure you have the necessary using statements for Anthropic and its exceptions. ```csharp using Anthropic; using Anthropic.Exceptions; using Anthropic.Models.Messages; AnthropicClient client = new(new Anthropic.Core.ClientOptions { ApiKey = "invalid-key", MaxRetries = 0, // disable retries for this example }); try { await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 256, Messages = [new() { Role = Role.User, Content = "Hello" }], }); } catch (AnthropicUnauthorizedException ex) { Console.WriteLine($"401 Unauthorized: {ex.Message}"); } catch (AnthropicRateLimitException ex) { Console.WriteLine($"429 Rate limited — retry after: {ex.Message}"); } catch (AnthropicBadRequestException ex) { Console.WriteLine($"400 Bad Request: {ex.Message}"); } catch (AnthropicNotFoundException ex) { Console.WriteLine($"404 Not Found: {ex.Message}"); } catch (AnthropicServiceException ex) { // Covers 5xx errors (retried automatically by default) Console.WriteLine($"5xx Server error ({ex.StatusCode}): {ex.Message}"); } catch (AnthropicIOException ex) { // Network-level error (connection refused, timeout, etc.) Console.WriteLine($"I/O error: {ex.Message}"); } ``` -------------------------------- ### Initialize AnthropicClient in C# Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Demonstrates initializing the AnthropicClient with default settings (reading from environment variables) and with explicit configuration options. Shows how to create a client with custom API key, base URL, retries, timeout, and response validation. Also illustrates creating a client with per-request option overrides. ```csharp using Anthropic; using Anthropic.Core; // Zero-config: reads ANTHROPIC_API_KEY from the environment AnthropicClient defaultClient = new(); // Explicit configuration via ClientOptions AnthropicClient client = new(new ClientOptions { ApiKey = "sk-ant-.", BaseUrl = "https://api.anthropic.com", MaxRetries = 3, Timeout = TimeSpan.FromSeconds(60), ResponseValidation = true, // validates response shape on deserialization }); // Per-request option overrides without mutating the original client var slowClient = client.Messages.WithOptions(opts => opts with { Timeout = TimeSpan.FromMinutes(5) }); // Default retry behaviour: 2 retries on 408, 409, 429, 5xx, and I/O errors // Default timeout: 10 minutes for non-streaming, scaled by MaxTokens for streaming ``` -------------------------------- ### AnthropicClient Initialization Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Demonstrates how to initialize the AnthropicClient with default settings or explicit configuration options. ```APIDOC ## `AnthropicClient` — Client Initialization and Configuration `AnthropicClient` is the root client. It reads `ANTHROPIC_API_KEY` and `ANTHROPIC_BASE_URL` from environment variables by default, but every option can be overridden via `ClientOptions`. `WithOptions` creates a lightweight copy of the client with modified settings without mutating the original. ```csharp using Anthropic; using Anthropic.Core; // Zero-config: reads ANTHROPIC_API_KEY from the environment AnthropicClient defaultClient = new(); // Explicit configuration via ClientOptions AnthropicClient client = new(new ClientOptions { ApiKey = "sk-ant-...", BaseUrl = "https://api.anthropic.com", MaxRetries = 3, Timeout = TimeSpan.FromSeconds(60), ResponseValidation = true, // validates response shape on deserialization }); // Per-request option overrides without mutating the original client var slowClient = client.Messages.WithOptions(opts => opts with { Timeout = TimeSpan.FromMinutes(5) }); // Default retry behaviour: 2 retries on 408, 409, 429, 5xx, and I/O errors // Default timeout: 10 minutes for non-streaming, scaled by MaxTokens for streaming ``` ``` -------------------------------- ### Beta Managed Agents - Environments, Agents, and Sessions Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Demonstrates the creation of environments, agents, and sessions, followed by sending a message and streaming events within the Managed Agents platform. ```APIDOC ## Beta Managed Agents — Environments, Agents, and Sessions The `client.Beta` namespace exposes the full Managed Agents platform. An *environment* is a persistent workspace; an *agent* defines model, tools, and skills; a *session* is a live conversation bound to an agent and environment. ```csharp using Anthropic; using Anthropic.Models.Beta.Agents; using Anthropic.Models.Beta.Environments; using Anthropic.Models.Beta.Sessions; using Anthropic.Models.Beta.Sessions.Events; AnthropicClient client = new(); // 1. Create an environment (persistent workspace) var environment = await client.Beta.Environments.Create( new EnvironmentCreateParams { Name = "my-environment" }); // 2. Create an agent with the built-in toolset var agent = await client.Beta.Agents.Create(new AgentCreateParams { Name = "my-agent", Model = BetaManagedAgentsModel.ClaudeSonnet4_6, System = "You are a helpful assistant.", Tools = [ new BetaManagedAgentsAgentToolset20260401Params { Type = BetaManagedAgentsAgentToolset20260401ParamsType.AgentToolset20260401, DefaultConfig = new BetaManagedAgentsAgentToolsetDefaultConfigParams { Enabled = true, PermissionPolicy = new BetaManagedAgentsAlwaysAllowPolicy { Type = BetaManagedAgentsAlwaysAllowPolicyType.AlwaysAllow, }, }, }, ], }); // 3. Create a session bound to the agent and environment var session = await client.Beta.Sessions.Create(new SessionCreateParams { Agent = agent.ID, EnvironmentID = environment.ID, }); // 4. Send a user message await client.Beta.Sessions.Events.Send(session.ID, new EventSendParams { Events = [ new BetaManagedAgentsUserMessageEventParams { Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage, Content = [new BetaManagedAgentsTextBlock { Type = BetaManagedAgentsTextBlockType.Text, Text = "Hello! What tools do you have access to?", }], }, ], }); // 5. Stream events until the session goes idle await foreach (var evt in client.Beta.Sessions.Events.StreamStreaming(session.ID)) { Console.WriteLine(evt); if (evt.TryPickSessionStatusIdleEvent(out _)) break; } ``` ``` -------------------------------- ### Run SDK Tests Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/CONTRIBUTING.md Run this command to execute the SDK's test suite. ```sh ./scripts/test ``` -------------------------------- ### Beta Files API - Upload and Mount Files in Sessions Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Shows how to upload binary files using the Beta Files API and then mount these files as resources within Managed Agent sessions. ```APIDOC ## Beta Files API — Upload and Mount Files in Sessions The `client.Beta.Files` service uploads binary content (CSV, PDF, images, etc.) and provides file IDs that can be mounted as resources inside Managed Agent sessions. ```csharp using Anthropic; using Anthropic.Core; using Anthropic.Models.Beta.Files; using Anthropic.Models.Beta.Sessions; AnthropicClient client = new(); // Upload a CSV file using var stream = File.OpenRead("data.csv"); var file = await client.Beta.Files.Upload(new FileUploadParams { File = new BinaryContent { Stream = stream, FileName = "data.csv", ContentType = new("text/csv"), }, }); Console.WriteLine($"Uploaded file ID: {file.ID}"); // Mount the file in a session as a resource var session = await client.Beta.Sessions.Create(new SessionCreateParams { Agent = "agent-id", EnvironmentID = "env-id", Resources = [ new BetaManagedAgentsFileResourceParams { Type = BetaManagedAgentsFileResourceParamsType.File, FileID = file.ID, MountPath = "data.csv", // accessible inside the session at /uploads/data.csv }, ], }); // List resources attached to the session var resources = await client.Beta.Sessions.Resources.List(session.ID); Console.WriteLine($"Session resources: {string.Join(", ", resources.Items.Select(r => r.ID))}"); ``` ``` -------------------------------- ### Add Local SDK Reference Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/CONTRIBUTING.md Use this command to reference a local version of the SDK in another project. ```sh dotnet add reference /path/to/sdk/src/Anthropic ``` -------------------------------- ### Upload and Mount Files in C# Sessions using Beta Files API Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt This snippet demonstrates how to upload binary files (like CSVs or PDFs) using the Beta Files API and then mount these uploaded files as resources within a Managed Agent session. Ensure the file path is correct and the file exists. ```csharp using Anthropic; using Anthropic.Core; using Anthropic.Models.Beta.Files; using Anthropic.Models.Beta.Sessions; AnthropicClient client = new(); // Upload a CSV file using var stream = File.OpenRead("data.csv"); var file = await client.Beta.Files.Upload(new FileUploadParams { File = new BinaryContent { Stream = stream, FileName = "data.csv", ContentType = new("text/csv"), }, }); Console.WriteLine($"Uploaded file ID: {file.ID}"); // Mount the file in a session as a resource var session = await client.Beta.Sessions.Create(new SessionCreateParams { Agent = "agent-id", EnvironmentID = "env-id", Resources = [ new BetaManagedAgentsFileResourceParams { Type = BetaManagedAgentsFileResourceParamsType.File, FileID = file.ID, MountPath = "data.csv", // accessible inside the session at /uploads/data.csv }, ], }); // List resources attached to the session var resources = await client.Beta.Sessions.Resources.List(session.ID); Console.WriteLine($"Session resources: {string.Join(", ", resources.Items.Select(r => r.ID))}"); ``` -------------------------------- ### Create Structured Output with `client.Messages.Create` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use the `Create` extension method to automatically generate a JSON schema from a C# class for structured outputs. The returned `StructuredMessage` provides a `.Parsed()` method to access the structured data. ```csharp using Anthropic; using Anthropic.Helpers; using Anthropic.Models.Messages; using Anthropic.Services; AnthropicClient client = new(); // Define the output model [SchemaClass("Extracted person information")] public class PersonInfo : StructuredOutputModel { [SchemaProperty("The person's full name")] public string Name { get; set; } = ""; [SchemaProperty("Age in years", Minimum = 0, Maximum = 150)] public int Age { get; set; } [SchemaProperty("Email address", Format = StringFormat.Email)] public string? Email { get; set; } [SchemaProperty("Employment status", Enum = new object[] { "employed", "unemployed", "student" })] public string Status { get; set; } = ""; } // Call the API with structured output var result = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 512, Messages = [ new() { Role = Role.User, Content = "Extract info: John Smith is a 32-year-old employed software engineer. Email: john@example.com", }, ], }); PersonInfo? person = result.Content[0].Parsed(); Console.WriteLine($"Name: {person?.Name}"); // Name: John Smith Console.WriteLine($"Age: {person?.Age}"); // Age: 32 Console.WriteLine($"Email: {person?.Email}"); // Email: john@example.com Console.WriteLine($"Status: {person?.Status}"); // Status: employed // Access token usage alongside parsed result Console.WriteLine($"Stop reason: {result.StopReason}"); Console.WriteLine($"Tokens: {result.Usage.InputTokens} in / {result.Usage.OutputTokens} out"); ``` -------------------------------- ### Automate Tool-Use Loop with `BetaToolRunner` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt The `BetaToolRunner` automates multi-turn conversations involving tool use. It calls the API, executes registered tools, feeds results back, and repeats until a final answer is produced or `maxIterations` is reached. Requires defining `BetaRunnableTool` instances with their schema and execution logic. ```csharp using System.Text.Json; using Anthropic; using Anthropic.Helpers.Beta; using Anthropic.Models.Beta.Messages; AnthropicClient client = new(); // Define runnable tools var weatherTool = new BetaRunnableTool { Name = "get_weather", Definition = new BetaTool { Name = "get_weather", Description = "Returns the current weather for a city.", InputSchema = new InputSchema { Properties = new Dictionary { ["city"] = JsonSerializer.SerializeToElement( new { type = "string", description = "City name" }), }, Required = ["city"], }, }, Run = (toolUse, _) => { var city = toolUse.Input.TryGetValue("city", out var c) ? c.GetString() ?? "" : ""; var result = city == "Paris" ? "Partly cloudy, 18°C, light breeze." : $"No data for {city}."; return Task.FromResult(result); }, }; var runner = client.Beta.Messages.ToolRunner( new MessageCreateParams { Model = Anthropic.Models.Messages.Model.ClaudeSonnet4_5, MaxTokens = 1024, Messages = [new() { Role = Role.User, Content = "What is the weather in Paris right now?" }], }, tools: [weatherTool], maxIterations: 5 ); // Iterate: each yielded BetaMessage is one API turn (tool-use or final answer) await foreach (BetaMessage message in runner) { Console.WriteLine($"Turn stop_reason: {message.StopReason}"); foreach (var block in message.Content) { if (block.TryPickText(out var text)) Console.WriteLine(text.Text); else if (block.TryPickToolUse(out var toolUse)) Console.WriteLine($" → called '{toolUse.Name}'"); } } // Or drive to completion and get just the final message // BetaMessage final = await runner.RunUntilDoneAsync(); ``` -------------------------------- ### Implement Prompt Caching with `WithCacheControl` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use `WithCacheControl` to add Anthropic's prompt-caching functionality to `AIContent` blocks. Content up to and including the marked block will be cached. Supports TTLs of 5 minutes (`Ttl.Ttl5m`) and 1 hour (`Ttl.Ttl1h`). ```csharp using Anthropic; using Anthropic.Models.Messages; using Microsoft.Extensions.AI; IChatClient chatClient = new AnthropicClient() .AsIChatClient("claude-sonnet-4-5", defaultMaxOutputTokens: 1024); string systemPrompt = "You are an expert .NET architect with 20 years of experience. " + string.Concat(Enumerable.Repeat("(padding) ", 500)); // simulate large prompt // Cache the system prompt for 1 hour — all tokens up to this block are cached var systemContent = new TextContent(systemPrompt) .WithCacheControl(Ttl.Ttl1h); var messages = new List { new(ChatRole.System, [systemContent]), new(ChatRole.User, "What are the SOLID principles?"), }; ChatResponse r1 = await chatClient.GetResponseAsync(messages); Console.WriteLine($"First call — cached tokens: {r1.Usage?.CachedInputTokenCount ?? 0}"); // Second call reuses the cache ChatResponse r2 = await chatClient.GetResponseAsync(messages); Console.WriteLine($"Second call — cached tokens: {r2.Usage?.CachedInputTokenCount ?? 0}"); // Expected: CachedInputTokenCount > 0 on the second call ``` -------------------------------- ### Format and Lint Code Source: https://github.com/anthropics/anthropic-sdk-csharp/blob/main/CONTRIBUTING.md Execute these scripts for code formatting and linting. ```sh ./scripts/format ./scripts/lint ``` -------------------------------- ### List and Retrieve Model Metadata with Anthropic SDK Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Lists all available Claude models with pagination support, or retrieves metadata for a specific model by ID. Use pagination to handle large numbers of models. ```csharp using Anthropic; using Anthropic.Models.Models; AnthropicClient client = new(); // List all models (paginated) ModelListPage page = await client.Models.List(); foreach (ModelInfo model in page.Data) Console.WriteLine($"{model.ID} — created: {model.CreatedAt:yyyy-MM-dd}"); // Paginate to the next page if (page.HasNextPage()) { ModelListPage next = await page.GetNextPage(); Console.WriteLine($"Next page has {next.Data.Count} models."); } // Retrieve a specific model ModelInfo info = await client.Models.Retrieve("claude-sonnet-4-5"); Console.WriteLine($"Display name: {info.DisplayName}"); Console.WriteLine($"Type: {info.Type}"); ``` -------------------------------- ### Integrate AnthropicClient with Microsoft.Extensions.AI IChatClient Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Adapts AnthropicClient to IChatClient from the Microsoft.Extensions.AI abstraction, enabling use with standard middleware like function invocation, logging, and caching. Use .AsBuilder() to chain middleware. ```csharp using Anthropic; using Microsoft.Extensions.AI; // Build an IChatClient with automatic function-invocation middleware IChatClient chatClient = new AnthropicClient() .AsIChatClient("claude-haiku-4-5") .AsBuilder() .UseFunctionInvocation() // middleware: auto-calls functions and loops .Build(); ChatOptions options = new() { Tools = [ AIFunctionFactory.Create( () => DateTime.UtcNow.ToString("o"), "get_utc_time", "Returns the current UTC time in ISO 8601 format." ), AIFunctionFactory.Create( (string city) => $"Sunny, 22°C in {city}", "get_weather", "Returns a mock weather report for the given city." ), ], }; // Non-streaming ChatResponse response = await chatClient.GetResponseAsync( "What time is it now, and what's the weather like in London?", options); Console.WriteLine(response.Text); // Streaming await foreach (ChatResponseUpdate update in chatClient.GetStreamingResponseAsync("Write a haiku about C#.", options)) { Console.Write(update); } ``` -------------------------------- ### Enable Extended Thinking with `ThinkingConfigEnabled` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Activate Claude's extended thinking mode by setting `Thinking` to `ThinkingConfigEnabled`. This generates explicit reasoning before the final answer. Control the token budget for internal monologue using `BudgetTokens`. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); var response = await client.Messages.Create(new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 4096, Thinking = new ThinkingConfigEnabled { BudgetTokens = 2048 }, Messages = [ new() { Role = Role.User, Content = "What is the 47th Fibonacci number? Show your reasoning." }, ], }); foreach (ContentBlock block in response.Content) { if (block.TryPickThinking(out ThinkingBlock? thinking)) Console.WriteLine($"[Thinking]\n{thinking.Thinking}\n"); else if (block.TryPickText(out TextBlock? text)) Console.WriteLine($"[Answer]\n{text.Text}"); } ``` -------------------------------- ### Create Single-Turn Message in C# Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Sends a synchronous request to the Messages API to create a single-turn message. Demonstrates extracting text content from the response and handling multi-turn conversations by accumulating message parameters. Also shows how to access usage metadata. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); // Single-turn var response = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 1024, Messages = [ new() { Role = Role.User, Content = "Explain async/await in C# in two sentences." }, ], }); string text = string.Join("", response.Content .Select(b => b.Value) .OfType() .Select(t => t.Text)); Console.WriteLine(text); // Expected: "Async/await in C# allows you to write asynchronous code that looks synchronous…" // Multi-turn conversation var messages = new List { new() { Role = Role.User, Content = "What is the capital of France?" }, new() { Role = Role.Assistant, Content = "The capital of France is Paris." }, new() { Role = Role.User, Content = "What is its population?" }, }; var followUp = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 256, System = "You are a helpful geography assistant.", Messages = messages, }); Console.WriteLine(followUp.Content[0].Value as TextBlock); // Usage metadata is available on the response Console.WriteLine($"Tokens used: {followUp.Usage.InputTokens} in / {followUp.Usage.OutputTokens} out"); ``` -------------------------------- ### `client.Messages.Create` — Structured Outputs Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt The `Create` extension method allows you to automatically generate a JSON schema from your C# class and inject it into the API request. This enables the model to return structured data that can be directly parsed into your specified C# type. ```APIDOC ## `client.Messages.Create` — Structured Outputs The `Create` extension method automatically generates a JSON schema from your C# class (using `[SchemaProperty]` and `[SchemaClass]` attributes) and injects it as the `output_config.format`. The returned `StructuredMessage` exposes a `.Parsed()` method on each text block. ### Request Example ```csharp using Anthropic; using Anthropic.Helpers; using Anthropic.Models.Messages; using Anthropic.Services; AnthropicClient client = new(); // Define the output model [SchemaClass("Extracted person information")] public class PersonInfo : StructuredOutputModel { [SchemaProperty("The person's full name")] public string Name { get; set; } = ""; [SchemaProperty("Age in years", Minimum = 0, Maximum = 150)] public int Age { get; set; } [SchemaProperty("Email address", Format = StringFormat.Email)] public string? Email { get; set; } [SchemaProperty("Employment status", Enum = new object[] { "employed", "unemployed", "student" })] public string Status { get; set; } = ""; } // Call the API with structured output var result = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 512, Messages = [ new() { Role = Role.User, Content = "Extract info: John Smith is a 32-year-old employed software engineer. Email: john@example.com", }, ], }); PersonInfo? person = result.Content[0].Parsed(); Console.WriteLine($"Name: {person?.Name}"); // Name: John Smith Console.WriteLine($"Age: {person?.Age}"); // Age: 32 Console.WriteLine($"Email: {person?.Email}"); // Email: john@example.com Console.WriteLine($"Status: {person?.Status}"); // Status: employed // Access token usage alongside parsed result Console.WriteLine($"Stop reason: {result.StopReason}"); Console.WriteLine($"Tokens: {result.Usage.InputTokens} in / {result.Usage.OutputTokens} out"); ``` ``` -------------------------------- ### Microsoft.Extensions.AI Integration Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Adapts AnthropicClient to IChatClient from the Microsoft.Extensions.AI abstraction, enabling use with the standard middleware pipeline (function invocation, logging, caching, etc.). ```APIDOC ## `AsIChatClient` — Microsoft.Extensions.AI Integration Adapts `AnthropicClient` to `IChatClient` from the `Microsoft.Extensions.AI` abstraction, enabling use with the standard middleware pipeline (function invocation, logging, caching, etc.). ```csharp using Anthropic; using Microsoft.Extensions.AI; // Build an IChatClient with automatic function-invocation middleware IChatClient chatClient = new AnthropicClient() .AsIChatClient("claude-haiku-4-5") .AsBuilder() .UseFunctionInvocation() // middleware: auto-calls functions and loops .Build(); ChatOptions options = new() { Tools = [ AIFunctionFactory.Create( () => DateTime.UtcNow.ToString("o"), "get_utc_time", "Returns the current UTC time in ISO 8601 format." ), AIFunctionFactory.Create( (string city) => $"Sunny, 22°C in {city}", "get_weather", "Returns a mock weather report for the given city." ), ], }; // Non-streaming ChatResponse response = await chatClient.GetResponseAsync( "What time is it now, and what's the weather like in London?", options); Console.WriteLine(response.Text); // Streaming await foreach (ChatResponseUpdate update in chatClient.GetStreamingResponseAsync("Write a haiku about C#.", options)) { Console.Write(update); } ``` ``` -------------------------------- ### Access Raw HTTP Response with `client.Messages.WithRawResponse` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use the `.WithRawResponse` accessor to obtain `HttpResponse` instead of `T` from message creation methods. This is useful for inspecting HTTP status codes, headers, or deferring deserialization. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); using var rawResponse = await client.Messages.WithRawResponse.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 256, Messages = [new() { Role = Role.User, Content = "Hello" }], }); Console.WriteLine($"HTTP status: {rawResponse.StatusCode}"); // 200 Console.WriteLine($"Request-id: {rawResponse.Headers["request-id"]}"); // Deserialize on demand Message message = await rawResponse.Deserialize(); Console.WriteLine(message.Content[0].Value as TextBlock); ``` -------------------------------- ### Model Metadata Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Lists all available Claude models with pagination support, or retrieves metadata for a specific model by ID. ```APIDOC ## `client.Models.List` / `client.Models.Retrieve` — Model Metadata Lists all available Claude models with pagination support, or retrieves metadata for a specific model by ID. ```csharp using Anthropic; using Anthropic.Models.Models; AnthropicClient client = new(); // List all models (paginated) ModelListPage page = await client.Models.List(); foreach (ModelInfo model in page.Data) Console.WriteLine($"{model.ID} — created: {model.CreatedAt:yyyy-MM-dd}"); // Paginate to the next page if (page.HasNextPage()) { ModelListPage next = await page.GetNextPage(); Console.WriteLine($"Next page has {next.Data.Count} models."); } // Retrieve a specific model ModelInfo info = await client.Models.Retrieve("claude-sonnet-4-5"); Console.WriteLine($"Display name: {info.DisplayName}"); Console.WriteLine($"Type: {info.Type}"); ``` ``` -------------------------------- ### Create and Process Message Batches with Anthropic SDK Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Submits multiple independent requests as a single batch job processed asynchronously. Results are streamed back as MessageBatchIndividualResponse objects via JSONL once the batch is complete. Poll until complete or use a webhook for production. ```csharp using Anthropic; using Anthropic.Models.Messages.Batches; AnthropicClient client = new(); // Create a batch of 3 requests MessageBatch batch = await client.Messages.Batches.Create(new BatchCreateParams { Requests = [ new() { CustomID = "req-1", Params = new() { Model = "claude-haiku-4-5", MaxTokens = 256, Messages = [new() { Role = Role.User, Content = "What is 2+2?" }], }, }, new() { CustomID = "req-2", Params = new() { Model = "claude-haiku-4-5", MaxTokens = 256, Messages = [new() { Role = Role.User, Content = "What is the capital of Japan?" }], }, }, ], }); Console.WriteLine($"Batch ID: {batch.ID}, status: {batch.ProcessingStatus}"); // Poll until complete (in production use a webhook or scheduled polling) MessageBatch current; do { await Task.Delay(TimeSpan.FromSeconds(5)); current = await client.Messages.Batches.Retrieve(batch.ID); Console.WriteLine($"Status: {current.ProcessingStatus}"); } while (current.ProcessingStatus.Value() == MessageBatchStatus.InProgress); // Stream results await foreach (MessageBatchIndividualResponse item in client.Messages.Batches.ResultsStreaming(batch.ID)) { Console.Write($"[{item.CustomID}] "); if (item.Result.TryPickSucceeded(out var success)) Console.WriteLine(((TextBlock?)success.Message.Content[0].Value)?.Text); else if (item.Result.TryPickErrored(out var error)) Console.WriteLine($"Error: {error.Error}"); } // Clean up await client.Messages.Batches.Delete(batch.ID); ``` -------------------------------- ### client.Messages.CreateStreaming Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Returns an IAsyncEnumerable that yields typed SSE events as they arrive. Use TryPickContentBlockDelta and its sub-pickers to extract incremental text or thinking deltas. ```APIDOC ## `client.Messages.CreateStreaming` — Server-Sent Event Streaming Returns an `IAsyncEnumerable` that yields typed SSE events as they arrive. Use `TryPickContentBlockDelta` and its sub-pickers to extract incremental text or thinking deltas. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); var parameters = new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 2048, Messages = [new() { Role = Role.User, Content = "Write a short poem about the ocean." }], }; await foreach (RawMessageStreamEvent rawEvent in client.Messages.CreateStreaming(parameters)) { if (rawEvent.TryPickContentBlockDelta(out var delta)) { if (delta.Delta.TryPickText(out var textDelta)) Console.Write(textDelta.Text); // incremental text else if (delta.Delta.TryPickThinking(out var thinkingDelta)) Console.Write(thinkingDelta.Thinking); // extended thinking delta } else if (rawEvent.TryPickMessageStop(out _)) { Console.WriteLine("\n[stream complete]"); } } ``` ``` -------------------------------- ### Aggregating Streaming Responses with `Aggregate` and `CollectAsync` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt The `Aggregate()` extension method consolidates an `IAsyncEnumerable` into a single `Message`. Use `MessageContentAggregator` with `CollectAsync` to observe events in real-time while building the full message. ```csharp using Anthropic; using Anthropic.Helpers; using Anthropic.Models.Messages; AnthropicClient client = new(); var parameters = new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 2048, Messages = [new() { Role = Role.User, Content = "Tell me a story about building the best SDK!" }], Thinking = new ThinkingConfigEnabled { BudgetTokens = 1024 }, }; IAsyncEnumerable stream = client.Messages.CreateStreaming(parameters); // Option A: aggregate the whole stream into one Message Message full = await stream.Aggregate(); Console.WriteLine(full); // Option B: observe events in real-time AND get the aggregated result afterwards var aggregator = new MessageContentAggregator(); await foreach (RawMessageStreamEvent e in stream.CollectAsync(aggregator)) { if (e.TryPickContentBlockDelta(out var d)) { if (d.Delta.TryPickThinking(out var t)) Console.Write(t.Thinking); else if (d.Delta.TryPickText(out var tx)) Console.Write(tx.Text); } } Message aggregated = aggregator.Message(); Console.WriteLine($"\nTotal output tokens: {aggregated.Usage.OutputTokens}"); ``` -------------------------------- ### Streaming Messages with `CreateStreaming` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use `CreateStreaming` to receive Server-Sent Events (SSE) as they arrive. Process incremental text or thinking deltas using `TryPickContentBlockDelta` and its sub-pickers. The stream yields `RawMessageStreamEvent` objects. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); var parameters = new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 2048, Messages = [new() { Role = Role.User, Content = "Write a short poem about the ocean." }], }; await foreach (RawMessageStreamEvent rawEvent in client.Messages.CreateStreaming(parameters)) { if (rawEvent.TryPickContentBlockDelta(out var delta)) { if (delta.Delta.TryPickText(out var textDelta)) Console.Write(textDelta.Text); // incremental text else if (delta.Delta.TryPickThinking(out var thinkingDelta)) Console.Write(thinkingDelta.Thinking); // extended thinking delta } else if (rawEvent.TryPickMessageStop(out _)) { Console.WriteLine("\n[stream complete]"); } } ``` -------------------------------- ### `client.Messages.WithRawResponse` — Raw HTTP Access Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt The `.WithRawResponse` accessor returns a service variant whose methods resolve to `HttpResponse` instead of `T`. This is useful for inspecting status codes, headers, or deferring deserialization of the response. ```APIDOC ## `client.Messages.WithRawResponse` — Raw HTTP Access The `.WithRawResponse` accessor returns a service variant whose methods resolve to `HttpResponse` instead of `T`. Useful for inspecting status codes, headers, or deferring deserialization. ### Request Example ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); using var rawResponse = await client.Messages.WithRawResponse.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 256, Messages = [new() { Role = Role.User, Content = "Hello" }], }); Console.WriteLine($"HTTP status: {rawResponse.StatusCode}"); // 200 Console.WriteLine($"Request-id: {rawResponse.Headers["request-id"]}"); // Deserialize on demand Message message = await rawResponse.Deserialize(); Console.WriteLine(message.Content[0].Value as TextBlock); ``` ``` -------------------------------- ### client.Messages.Create — Single-Turn Message Creation Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Sends a synchronous (non-streaming) request to the Messages API and returns a fully deserialized `Message`. Multi-turn conversations are built by accumulating `MessageParam` objects in the `Messages` list. ```APIDOC ## `client.Messages.Create` — Single-Turn Message Creation Sends a synchronous (non-streaming) request to the Messages API and returns a fully deserialized `Message`. Multi-turn conversations are built by accumulating `MessageParam` objects in the `Messages` list. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); // Single-turn var response = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 1024, Messages = [ new() { Role = Role.User, Content = "Explain async/await in C# in two sentences." }, ], }); string text = string.Join("", response.Content .Select(b => b.Value) .OfType() .Select(t => t.Text)); Console.WriteLine(text); // Expected: "Async/await in C# allows you to write asynchronous code that looks synchronous…" // Multi-turn conversation var messages = new List { new() { Role = Role.User, Content = "What is the capital of France?" }, new() { Role = Role.Assistant, Content = "The capital of France is Paris." }, new() { Role = Role.User, Content = "What is its population?" }, }; var followUp = await client.Messages.Create(new MessageCreateParams { Model = "claude-sonnet-4-5", MaxTokens = 256, System = "You are a helpful geography assistant.", Messages = messages, }); Console.WriteLine(followUp.Content[0].Value as TextBlock); // Usage metadata is available on the response Console.WriteLine($"Tokens used: {followUp.Usage.InputTokens} in / {followUp.Usage.OutputTokens} out"); ``` ``` -------------------------------- ### Extended Thinking (`ThinkingConfigEnabled`) Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Enables Claude's extended thinking mode, which causes the model to produce explicit reasoning before its final answer. You can control the token budget allocated to this internal monologue using `BudgetTokens`. ```APIDOC ## Extended Thinking (`ThinkingConfigEnabled`) Enables Claude's extended thinking mode, which causes the model to produce explicit reasoning (`ThinkingBlock`) before its final answer. Set `BudgetTokens` to control how much of the token budget is allocated to the internal monologue. ### Request Example ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); var response = await client.Messages.Create(new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 4096, Thinking = new ThinkingConfigEnabled { BudgetTokens = 2048 }, Messages = [ new() { Role = Role.User, Content = "What is the 47th Fibonacci number? Show your reasoning." }, ], }); foreach (ContentBlock block in response.Content) { if (block.TryPickThinking(out ThinkingBlock? thinking)) Console.WriteLine($"[Thinking]\n{thinking.Thinking}\n"); else if (block.TryPickText(out TextBlock? text)) Console.WriteLine($"[Answer]\n{text.Text}"); } ``` ``` -------------------------------- ### responseUpdates.Aggregate() Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt The Aggregate() extension method on IAsyncEnumerable consumes the entire stream and returns a single aggregated Message, identical to what Create would return. The MessageContentAggregator helper allows real-time observation while building the full message in parallel. ```APIDOC ## `responseUpdates.Aggregate()` — Streaming Aggregation The `Aggregate()` extension method on `IAsyncEnumerable` consumes the entire stream and returns a single aggregated `Message`, identical to what `Create` would return. The `MessageContentAggregator` helper allows real-time observation while building the full message in parallel. ```csharp using Anthropic; using Anthropic.Helpers; using Anthropic.Models.Messages; AnthropicClient client = new(); var parameters = new MessageCreateParams { Model = Model.ClaudeSonnet4_5, MaxTokens = 2048, Messages = [new() { Role = Role.User, Content = "Tell me a story about building the best SDK!" }], Thinking = new ThinkingConfigEnabled { BudgetTokens = 1024 }, }; IAsyncEnumerable stream = client.Messages.CreateStreaming(parameters); // Option A: aggregate the whole stream into one Message Message full = await stream.Aggregate(); Console.WriteLine(full); // Option B: observe events in real-time AND get the aggregated result afterwards var aggregator = new MessageContentAggregator(); await foreach (RawMessageStreamEvent e in stream.CollectAsync(aggregator)) { if (e.TryPickContentBlockDelta(out var d)) { if (d.Delta.TryPickThinking(out var t)) Console.Write(t.Thinking); else if (d.Delta.TryPickText(out var tx)) Console.Write(tx.Text); } } Message aggregated = aggregator.Message(); Console.WriteLine($"\nTotal output tokens: {aggregated.Usage.OutputTokens}"); ``` ``` -------------------------------- ### Counting Tokens with `CountTokens` Source: https://context7.com/anthropics/anthropic-sdk-csharp/llms.txt Use `CountTokens` to determine the token count of a request without executing the completion. This is useful for managing context window limits or estimating costs. ```csharp using Anthropic; using Anthropic.Models.Messages; AnthropicClient client = new(); var countParams = new MessageCountTokensParams { Model = "claude-sonnet-4-5", Messages = [ new() { Role = Role.User, Content = "How many tokens is this message?" }, ], System = "You are a helpful assistant.", }; MessageTokensCount result = await client.Messages.CountTokens(countParams); Console.WriteLine($"Input token count: {result.InputTokens}"); // Expected output: Input token count: 21 ```