ClaudeAgentSdk.DotNet 0.1.0

dotnet add package ClaudeAgentSdk.DotNet --version 0.1.0
                    
NuGet\Install-Package ClaudeAgentSdk.DotNet -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ClaudeAgentSdk.DotNet" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ClaudeAgentSdk.DotNet" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ClaudeAgentSdk.DotNet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ClaudeAgentSdk.DotNet --version 0.1.0
                    
#r "nuget: ClaudeAgentSdk.DotNet, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ClaudeAgentSdk.DotNet@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ClaudeAgentSdk.DotNet&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ClaudeAgentSdk.DotNet&version=0.1.0
                    
Install as a Cake Tool

Claude Agent SDK for .NET

NuGet Build License

Typed, AOT-compatible C# SDK for the Claude Code CLI agent protocol. Port of the official Python Claude Agent SDK.

Installation

dotnet add package ClaudeAgentSdk.DotNet

Requires .NET 10+ and the Claude Code CLI installed and available on your PATH.

Quick Start

using ClaudeAgentSdk;
using ClaudeAgentSdk.Messages;

await foreach (var message in Claude.QueryAsync("What is 2 + 2?"))
{
    if (message is AssistantMessage { Text: var text })
        Console.WriteLine($"Claude: {text}");
}

One-Shot API

Claude.QueryAsync streams messages from a single prompt. Claude.QueryTextAsync returns just the final text.

// Stream all messages
var options = new ClaudeClientOptions
{
    SystemPrompt = "You are a helpful assistant that explains things simply.",
    MaxTurns = 1,
};

await foreach (var message in Claude.QueryAsync("Explain what C# is in one sentence.", options))
{
    if (message is AssistantMessage { Text: var text })
        Console.WriteLine($"Claude: {text}");
}

// Get text only — no streaming
string reply = await Claude.QueryTextAsync("What is 2 + 2?");

Structured Output

Claude.QueryAsync<T> auto-derives a JSON schema from your source-generated JsonTypeInfo<T> and deserializes the result — one line, fully AOT-safe.

using System.Text.Json.Serialization;
using ClaudeAgentSdk;

var person = await Claude.QueryAsync(
    "Extract person info: John Smith is 35 years old, works as a software engineer.",
    ExampleJsonContext.Default.PersonInfo);

Console.WriteLine($"{person?.Name}, age {person?.Age}");

public sealed record PersonInfo
{
    [JsonPropertyName("name")]
    public string Name { get; init; } = "";

    [JsonPropertyName("age")]
    public int Age { get; init; }
}

[JsonSerializable(typeof(PersonInfo))]
internal sealed partial class ExampleJsonContext : JsonSerializerContext;

Stateful Client

ClaudeClient supports multi-turn conversations with session persistence, interrupts, and runtime control.

await using var client = new ClaudeClient(new ClaudeClientOptions
{
    SystemPrompt = "You are a helpful coding assistant.",
    Model = "sonnet",
});

// Turn 1
await foreach (var msg in client.SendAsync("What's the capital of France?"))
    if (msg is AssistantMessage { Text: var text }) Console.WriteLine($"Claude: {text}");

// Turn 2 — Claude remembers context
await foreach (var msg in client.SendAsync("What's the population of that city?"))
    if (msg is AssistantMessage { Text: var text }) Console.WriteLine($"Claude: {text}");

Message Handling

await foreach (var message in client.SendAsync("Create a hello.py file"))
{
    switch (message)
    {
        case AssistantMessage { Content: var content }:
            foreach (var block in content)
            {
                switch (block)
                {
                    case TextBlock { Text: var text }:
                        Console.WriteLine($"Claude: {text}");
                        break;
                    case ToolUseBlock { Name: var name, Input: var input }:
                        Console.WriteLine($"Tool: {name}");
                        break;
                }
            }
            break;

        case ResultMessage { TotalCostUsd: > 0 and var cost }:
            Console.WriteLine($"Cost: ${cost:F4}");
            break;
    }
}

Tools

By default, Claude has access to the full Claude Code toolset. AllowedTools is a permission allowlist that auto-approves listed tools. DisallowedTools blocks specific tools entirely.

var options = new ClaudeClientOptions
{
    AllowedTools = ["Read", "Write", "Bash"],
    PermissionMode = PermissionMode.AcceptEdits,
};

Custom Tools (In-Process MCP Servers)

Define tools that run inside your application with zero IPC overhead. No subprocess management, no external server processes.

using System.Text.Json.Serialization;
using ClaudeAgentSdk.Mcp;
using ClaudeAgentSdk.Mcp.Sdk;

// Define input type — schema auto-derived from JsonTypeInfo
public sealed record TwoNumbers
{
    [JsonPropertyName("a")] public double A { get; init; }
    [JsonPropertyName("b")] public double B { get; init; }
}

[JsonSerializable(typeof(TwoNumbers))]
internal sealed partial class CalcContext : JsonSerializerContext;

var tools = new SdkMcpTool[]
{
    SdkMcpTool.Create<TwoNumbers>("add", "Add two numbers",
        CalcContext.Default.TwoNumbers,
        (input, _) => McpToolResult.Text($"{input.A + input.B}")),
};

var calculator = McpSdkServerConfig.Create("calculator", tools);

var options = new ClaudeClientOptions
{
    McpServers = new Dictionary<string, McpServerConfig>
    {
        ["calc"] = calculator,
    },
    AllowedTools = calculator.GetQualifiedToolNames("calc"), // mcp__calc__add, etc.
};

You can mix SDK and external MCP servers:

var options = new ClaudeClientOptions
{
    McpServers = new Dictionary<string, McpServerConfig>
    {
        ["internal"] = sdkServer,                           // in-process
        ["external"] = new McpStdioServerConfig("my-tool"), // subprocess
    },
};

Hooks

Hooks are functions invoked at specific points of the agent loop for deterministic processing and automated feedback. Supports both sync and async callbacks.

using ClaudeAgentSdk.Hooks;

HookOutput CheckBashCommand(HookInput input)
{
    if (input is not PreToolUseInput { ToolName: "Bash" } pre)
        return HookOutput.Empty;

    string command = pre.ToolInput.TryGetProperty("command", out var cmd)
        ? cmd.GetString() ?? "" : "";

    if (command.Contains("rm -rf"))
    {
        return new HookOutput
        {
            HookSpecificOutput = new PreToolUseOutput
            {
                PermissionDecision = "deny",
                PermissionDecisionReason = "Dangerous command blocked",
            },
        };
    }

    return HookOutput.Empty;
}

var options = new ClaudeClientOptions
{
    AllowedTools = ["Bash"],
    Hooks = new Dictionary<HookEvent, IReadOnlyList<HookMatcher>>
    {
        [HookEvent.PreToolUse] = [HookMatcher.Create("Bash", CheckBashCommand)],
    },
};

Hook events: PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Stop, SubagentStop, PreCompact, Notification, SubagentStart, PermissionRequest.

Permission Callbacks

Fine-grained tool permission control via CanUseTool:

using ClaudeAgentSdk.Permissions;

var options = new ClaudeClientOptions
{
    CanUseTool = async (toolName, input, context, ct) =>
    {
        if (toolName is "Read" or "Grep")
            return new PermissionResultAllow();

        if (toolName is "Bash")
        {
            var command = input.TryGetProperty("command", out var cmd)
                ? cmd.GetString() ?? "" : "";

            if (command.Contains("rm -rf"))
                return new PermissionResultDeny { Message = "Dangerous command blocked" };
        }

        return new PermissionResultAllow();
    },
};

Agents

Define specialized sub-agents with their own tools, models, and prompts:

using ClaudeAgentSdk.Agents;

var options = new ClaudeClientOptions
{
    Agents = new Dictionary<string, AgentDefinition>
    {
        ["code-reviewer"] = new()
        {
            Description = "Reviews code for best practices",
            Prompt = "You are a code reviewer. Be concise.",
            Tools = ["Read", "Grep"],
            Model = AgentModel.Sonnet,
        },
    },
};

await foreach (var msg in Claude.QueryAsync(
    "Use the code-reviewer agent to review src/Program.cs", options))
{
    if (msg is AssistantMessage { Text: var text })
        Console.WriteLine(text);
}

Types

MessagesAssistantMessage, UserMessage, SystemMessage, ResultMessage, StreamEvent, RateLimitEvent

Content BlocksTextBlock, ThinkingBlock, ToolUseBlock, ToolResultBlock

Task MessagesTaskStartedMessage, TaskProgressMessage, TaskNotificationMessage

See Messages and Content Blocks for full definitions.

Error Handling

using ClaudeAgentSdk.Exceptions;

try
{
    await foreach (var msg in Claude.QueryAsync("Hello")) { }
}
catch (CliNotFoundException)
{
    Console.WriteLine("Claude Code CLI not found — install it first");
}
catch (CliConnectionException)
{
    Console.WriteLine("Failed to connect to Claude CLI process");
}
catch (MessageParseException e)
{
    Console.WriteLine($"Failed to parse response: {e.Message}");
}

Examples

See the examples/ directory for 12 complete projects:

Example Description
QuickStart Basic queries, options, and tool usage
StructuredOutput Typed JSON responses with AOT source generation
StreamingClient Multi-turn conversations, interrupts, message handling
McpCalculator In-process MCP server with calculator tools
Hooks PreToolUse, PostToolUse, and UserPromptSubmit hooks
ToolPermissions Fine-grained permission callbacks
Agents Custom agent definitions
ToolsConfiguration Allowed and disallowed tools
SystemPrompt Custom system prompts
MaxBudget Budget limits and cost control
PartialMessages Real-time streaming with partial updates
StderrCallback CLI debug output capture
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 112 4/5/2026
0.0.8 108 3/24/2026
0.0.7 103 3/24/2026
0.0.6 100 3/23/2026
0.0.5 99 3/22/2026
0.0.4 93 3/22/2026
0.0.3 96 3/22/2026
0.0.2 97 3/22/2026