ToolCallParser 0.6.5

dotnet add package ToolCallParser --version 0.6.5
                    
NuGet\Install-Package ToolCallParser -Version 0.6.5
                    
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="ToolCallParser" Version="0.6.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToolCallParser" Version="0.6.5" />
                    
Directory.Packages.props
<PackageReference Include="ToolCallParser" />
                    
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 ToolCallParser --version 0.6.5
                    
#r "nuget: ToolCallParser, 0.6.5"
                    
#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 ToolCallParser@0.6.5
                    
#: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=ToolCallParser&version=0.6.5
                    
Install as a Cake Addin
#tool nuget:?package=ToolCallParser&version=0.6.5
                    
Install as a Cake Tool

ToolCallParser

NuGet License: MIT .NET

Multi-provider tool call parsing and normalization for LLM applications.

Features

  • Unified Interface - Parse tool calls from any LLM provider into a common format
  • Auto-Detection - Automatically detect the provider from response format
  • 5 provider parsers - OpenAI, Anthropic, Google, Cohere, AWS Bedrock — covering OpenAI, Azure, xAI, Mistral, DeepSeek, Claude, Gemini, Command R, and Bedrock. Two of them read more than one wire format: OpenAI (Chat Completions + Responses) and Google (generateContent + Interactions)
  • Self-hosted support - Any OpenAI-compatible endpoint (Ollama, vLLM, LM Studio, LocalAI, TGI, GpuStack, Qwen, …) via Provider.OpenAICompatible
  • Result Formatting - Format tool results back to provider-specific format
  • Extensible - Implement IToolCallParser (with CanParse for auto-detection) for new formats

Installation

dotnet add package ToolCallParser

Quick Start

Auto-Detection Parsing

using ToolCallParser;

// Parse tool calls with automatic provider detection
var response = """
{
  "choices": [{
    "message": {
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"location\":\"Tokyo\",\"unit\":\"celsius\"}"
        }
      }]
    }
  }]
}
""";

var toolCalls = ToolCallParserFactory.Parse(response);

foreach (var call in toolCalls)
{
    Console.WriteLine($"Tool: {call.Name}");
    Console.WriteLine($"ID: {call.Id}");
    Console.WriteLine($"Args: {call.Arguments}");
}

Provider-Specific Parsing

// OpenAI-compatible (Mistral, xAI, DeepSeek, or any OpenAI-compatible endpoint)
var openAiParser = ToolCallParserFactory.GetParser(Provider.OpenAI);

// Anthropic Claude
var claudeParser = ToolCallParserFactory.GetParser(Provider.Anthropic);

// Google Gemini
var geminiParser = ToolCallParserFactory.GetParser(Provider.Google);

// AWS Bedrock
var bedrockParser = ToolCallParserFactory.GetParser(Provider.Bedrock);

// Cohere Command R
var cohereParser = ToolCallParserFactory.GetParser(Provider.Cohere);

Supported Providers

Commercial Cloud

Provider Format Documentation
OpenAI tool_calls (Chat Completions) + function_call output items (Responses API) docs
Azure OpenAI OpenAI-compatible docs
Anthropic (Claude) tool_use blocks docs
Google Gemini functionCall parts (generateContent) + function_call steps (Interactions API) docs
xAI (Grok) OpenAI-compatible docs
Mistral OpenAI-compatible docs
Cohere Unique format docs
DeepSeek OpenAI-compatible docs
AWS Bedrock toolUse blocks (Converse); also exposes OpenAI-compatible Chat Completions + Responses endpoints, which detect as Provider.OpenAI docs

Open Source / Self-Hosted

Self-hosted runtimes speak the OpenAI tool-calling wire format, so they are handled by a single Provider.OpenAICompatible value rather than a per-runtime enum member:

// Ollama, vLLM, LM Studio, LocalAI, TGI, GpuStack, Qwen, and any other OpenAI-compatible server
var parser = ToolCallParserFactory.GetParser(Provider.OpenAICompatible);

Auto-detection (ToolCallParserFactory.Parse) also classifies these responses as the OpenAI format, so an explicit provider is only needed when you skip detection.

Format Categories

// Check format compatibility
var provider = Provider.OpenAICompatible;

if (provider.IsOpenAICompatible())
{
    Console.WriteLine("Uses OpenAI tool_calls format");
}

if (provider.IsAnthropicCompatible())
{
    Console.WriteLine("Uses Anthropic tool_use format");
}

// Get documentation URL
var docUrl = provider.GetDocumentationUrl();

Response Format Examples

OpenAI Format (Most Common)

{
  "choices": [{
    "message": {
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"location\":\"Tokyo\"}"
        }
      }]
    }
  }]
}

Anthropic Format

{
  "content": [
    {"type": "text", "text": "I'll check the weather."},
    {
      "type": "tool_use",
      "id": "toolu_01XYZ",
      "name": "get_weather",
      "input": {"location": "Paris"}
    }
  ],
  "stop_reason": "tool_use"
}

Google Gemini Format

{
  "candidates": [{
    "content": {
      "parts": [{
        "functionCall": {
          "name": "get_weather",
          "args": {"location": "London"}
        }
      }]
    }
  }]
}

AWS Bedrock Format

{
  "output": {
    "message": {
      "content": [{
        "toolUse": {
          "toolUseId": "tooluse_abc",
          "name": "get_weather",
          "input": {"location": "NYC"}
        }
      }]
    }
  },
  "stopReason": "tool_use"
}

Working with Arguments

var toolCall = toolCalls[0];

// Get a specific argument
var location = toolCall.GetArgument<string>("location");

// Get all arguments as a typed object
var weather = toolCall.GetArguments<WeatherArgs>();

// Check if argument exists
if (toolCall.HasArgument("unit"))
{
    var unit = toolCall.GetArgument<string>("unit");
}

public record WeatherArgs(string Location, string Unit = "celsius");

Formatting Results

// Create tool results
var results = new[]
{
    ToolCallResult.Success("call_abc123", "Temperature: 22°C", "get_weather"),
    ToolCallResult.Failure("call_def456", "Location not found", "get_weather")
};

// Format for OpenAI
var openAiParser = ToolCallParserFactory.GetParser(Provider.OpenAI);
var openAiResults = openAiParser.FormatResults(results);

// Format for Anthropic
var anthropicParser = ToolCallParserFactory.GetParser(Provider.Anthropic);
var claudeResults = anthropicParser.FormatResults(results);

// Format for Google Gemini (generateContent)
var geminiParser = ToolCallParserFactory.GetParser(Provider.Google);
var geminiResults = geminiParser.FormatResults(results);

Google serves tool calling through two wire formats, and a result payload carries nothing that says which one it is headed for — so for the Interactions surface the caller names it. The call_id sent back is the step id that parsing preserved:

using ToolCallParser.Parsers;

var parser = new GoogleToolCallParser();
var interactionsResults = parser.FormatResults(results, GoogleSurface.Interactions);
// [{ "type": "function_result", "call_id": "...", "name": "...", "result": {...}, "is_error": false }]

Provider Detection

// Auto-detect provider from response
var provider = ToolCallParserFactory.DetectProvider(jsonResponse);

switch (provider)
{
    case Provider.OpenAI:
        Console.WriteLine("OpenAI format detected");
        break;
    case Provider.Anthropic:
        Console.WriteLine("Anthropic format detected");
        break;
    case Provider.Google:
        Console.WriteLine("Gemini format detected");
        break;
    case Provider.Bedrock:
        Console.WriteLine("AWS Bedrock format detected");
        break;
    case Provider.Auto:
        Console.WriteLine("Could not auto-detect");
        break;
}

Custom Parsers

Implement IToolCallParser and use it directly. The built-in ToolCallParserFactory exposes a fixed set of parsers and is not a mutable registry — a custom parser is just a class you own:

public class CustomProviderParser : IToolCallParser
{
    public Provider Provider => Provider.OpenAICompatible;
    public IReadOnlyList<ToolCall> Parse(string response) => throw new NotImplementedException(); // your parsing
    public IReadOnlyList<ToolCall> Parse(JsonElement element) => throw new NotImplementedException(); // your parsing
    public bool HasToolCalls(string response) => throw new NotImplementedException(); // your parsing
    public bool HasToolCalls(JsonElement element) => throw new NotImplementedException(); // your parsing
    // Optional: override CanParse for auto-detection; defaults to HasToolCalls.
    public bool CanParse(JsonElement element) => throw new NotImplementedException(); // your parsing
    public string FormatResults(IEnumerable<ToolCallResult> results) => throw new NotImplementedException(); // your parsing
}

// Use it directly
var parser = new CustomProviderParser();
var toolCalls = parser.Parse(response);

API Reference

ToolCall

public sealed record ToolCall
{
    public required string Id { get; init; }
    public required string Name { get; init; }
    public required string Arguments { get; init; }  // JSON string

    public JsonDocument GetArgumentsAsJson();
    public T? GetArguments<T>(JsonSerializerOptions? options = null);
    public T? GetArgument<T>(string name, JsonSerializerOptions? options = null);
    public bool HasArgument(string name);
}

ToolCallResult

public sealed record ToolCallResult
{
    public required string ToolCallId { get; init; }
    public string? ToolName { get; init; }
    public required string Content { get; init; }
    public bool IsSuccess { get; init; } = true;
    public string? ErrorMessage { get; init; }

    public static ToolCallResult Success(string toolCallId, string content, string? toolName = null);
    public static ToolCallResult Failure(string toolCallId, string errorMessage, string? toolName = null);
}

ProviderExtensions

public static class ProviderExtensions
{
    public static ProviderFormat GetFormat(this Provider provider);
    public static bool IsOpenAICompatible(this Provider provider);
    public static bool IsAnthropicCompatible(this Provider provider);
    public static string? GetDocumentationUrl(this Provider provider);
}

Requirements

  • .NET 10.0
  • System.Text.Json (included in .NET)

Documentation

License

MIT License - see LICENSE for details.

Contributing

Contributions welcome! Especially for adding support for new providers.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/new-provider)
  3. Add parser in src/ToolCallParser/Parsers/
  4. Add tests in tests/ToolCallParser.Tests/
  5. Update Provider enum and factory
  6. Submit a Pull Request

See docs/tool-call-format-guide.md for detailed instructions.


Made with care by iyulab

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 (2)

Showing the top 2 NuGet packages that depend on ToolCallParser:

Package Downloads
IronHive.Cli.Core

IronHive CLI Core - Agent loop, tools, session management, and provider integrations for building AI-powered CLI tools

IronHive.Host.Core

IronHive Host Core - Agent loop, tools, session management, and provider integrations for building reusable AI agent hosts (CLI, server, embedded)

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.5 78 9/30/2026
0.6.4 88 9/30/2026
0.6.3 86 9/28/2026
0.6.2 100 9/17/2026
0.6.1 108 9/9/2026
0.6.0 169 8/2/2026
0.5.0 122 8/2/2026
0.4.0 221 7/21/2026
0.3.1 123 7/6/2026
0.3.0 126 7/6/2026
0.2.1 1,531 2/20/2026
0.1.0 179 1/28/2026