Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
csharp/claude-api/tool-use.md
1# Tool Use — C#23For conceptual overview (tool definitions, tool choice, tips), see [shared/tool-use-concepts.md](../../shared/tool-use-concepts.md).45## Tool Use67### Defining a tool89`Tool` (NOT `ToolParam`) with an `InputSchema` record. `InputSchema.Type` is auto-set to `"object"` by the constructor — don't set it. `ToolUnion` has an implicit conversion from `Tool`, triggered by the collection expression `[...]`.1011```csharp12using System.Text.Json;13using Anthropic.Models.Messages;1415var parameters = new MessageCreateParams16{17Model = Model.ClaudeSonnet4_6,18MaxTokens = 16000,19Tools = [20new Tool {21Name = "get_weather",22Description = "Get the current weather in a given location",23InputSchema = new() {24Properties = new Dictionary<string, JsonElement> {25["location"] = JsonSerializer.SerializeToElement(26new { type = "string", description = "City name" }),27},28Required = ["location"],29},30},31],32Messages = [new() { Role = Role.User, Content = "Weather in Paris?" }],33};34```3536Derived from `anthropic-sdk-csharp/src/Anthropic/Models/Messages/Tool.cs` and `ToolUnion.cs:799` (implicit conversion).3738See [shared tool use concepts](../../shared/tool-use-concepts.md) for the loop pattern.39### Converting response content to the follow-up assistant message4041When echoing Claude's response back in the assistant turn, **there is no `.ToParam()` helper** — manually reconstruct each `ContentBlock` variant as its `*Param` counterpart. Do NOT use `new ContentBlockParam(block.Json)`: it compiles and serializes, but `.Value` stays `null` so `TryPick*`/`Validate()` fail (degraded JSON pass-through, not the typed path).4243```csharp44using Anthropic.Models.Messages;4546Message response = await client.Messages.Create(parameters);4748// No .ToParam() — reconstruct per variant. Implicit conversions from each49// *Param type to ContentBlockParam mean no explicit wrapper.50List<ContentBlockParam> assistantContent = [];51List<ContentBlockParam> toolResults = [];52foreach (ContentBlock block in response.Content)53{54if (block.TryPickText(out TextBlock? text))55{56assistantContent.Add(new TextBlockParam { Text = text.Text });57}58else if (block.TryPickThinking(out ThinkingBlock? thinking))59{60// Signature MUST be preserved — the API rejects tampering61assistantContent.Add(new ThinkingBlockParam62{63Thinking = thinking.Thinking,64Signature = thinking.Signature,65});66}67else if (block.TryPickRedactedThinking(out RedactedThinkingBlock? redacted))68{69assistantContent.Add(new RedactedThinkingBlockParam { Data = redacted.Data });70}71else if (block.TryPickToolUse(out ToolUseBlock? toolUse))72{73// ToolUseBlock has required Caller; ToolUseBlockParam.Caller is optional — don't copy it74assistantContent.Add(new ToolUseBlockParam75{76ID = toolUse.ID,77Name = toolUse.Name,78Input = toolUse.Input,79});80// Execute the tool; collect ONE result per tool_use block — the API81// rejects the follow-up if any tool_use ID lacks a matching tool_result.82string result = ExecuteYourTool(toolUse.Name, toolUse.Input);83toolResults.Add(new ToolResultBlockParam84{85ToolUseID = toolUse.ID,86Content = result,87});88}89}9091// Follow-up: prior messages + assistant echo + user tool_result(s)92List<MessageParam> followUpMessages =93[94.. parameters.Messages,95new() { Role = Role.Assistant, Content = assistantContent },96new() { Role = Role.User, Content = toolResults },97];98```99100`ToolResultBlockParam` has no tuple constructor — use the object initializer. `Content` is a string-or-list union; a plain `string` implicitly converts.101102---103104## Structured Output105106```csharp107OutputConfig = new OutputConfig {108Format = new JsonOutputFormat {109Schema = new Dictionary<string, JsonElement> {110["type"] = JsonSerializer.SerializeToElement("object"),111["properties"] = JsonSerializer.SerializeToElement(112new { name = new { type = "string" } }),113["required"] = JsonSerializer.SerializeToElement(new[] { "name" }),114},115},116},117```118119`JsonOutputFormat.Type` is auto-set to `"json_schema"` by the constructor. `Schema` is `required`.120121---122123## Anthropic-Defined Tools124125Web search, bash, text editor, and code execution are Anthropic-defined tools with built-in schemas. Web search and code execution are server-executed; bash and text editor are client-executed (you handle the `tool_use` locally — see `shared/tool-use-concepts.md`). Type names are version-suffixed; constructors auto-set `name`/`type`. **Wrap each in `new ToolUnion(...)` explicitly.**126127```csharp128Tools = [129new ToolUnion(new WebSearchTool20260209()),130new ToolUnion(new ToolBash20250124()),131new ToolUnion(new ToolTextEditor20250728()),132new ToolUnion(new CodeExecutionTool20260120()),133],134```135136Also available: `new ToolUnion(new WebFetchTool20260209())`, `new ToolUnion(new MemoryTool20250818())`. `WebSearchTool20260209` optionals: `AllowedDomains`, `BlockedDomains`, `MaxUses`, `UserLocation`.137138---139140## Tool Runner (Beta)141142The C# SDK provides a `BetaToolRunner` for automatic tool execution loops. Define tools with raw JSON schemas, and the runner handles the API call → tool execution → result feedback loop.143144```csharp145using Anthropic.Models.Beta.Messages;146147// Define tools and create params as shown in the Tool Use section above,148// but using the beta namespace types (BetaToolUnion, etc.)149var runner = client.Beta.Messages.ToolRunner(betaParams);150151await foreach (BetaMessage message in runner)152{153foreach (var block in message.Content)154{155if (block.TryPickText(out var text))156{157Console.WriteLine(text.Text);158}159}160}161```162163---164165