Thanks to visit codestin.com
Credit goes to github.com

Skip to content

iyulab/ToolCallParser

Repository files navigation

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
  • 20+ Providers - OpenAI, Anthropic, Google, xAI, Mistral, Cohere, DeepSeek, AWS Bedrock, and more
  • OpenSource Support - Ollama, vLLM, GpuStack, Qwen, LMStudio, LocalAI, TGI
  • Result Formatting - Format tool results back to provider-specific format
  • Extensible - Register custom parsers for new providers

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, Ollama, etc.)
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 docs
Azure OpenAI OpenAI-compatible docs
Anthropic (Claude) tool_use blocks docs
Google Gemini functionCall docs
xAI (Grok) OpenAI-compatible docs
Mistral OpenAI-compatible docs
Cohere Unique format docs
DeepSeek OpenAI-compatible docs
AWS Bedrock toolUse blocks docs

Open Source / Self-Hosted

Provider Format Documentation
Ollama OpenAI-compatible docs
GpuStack OpenAI-compatible docs
vLLM OpenAI-compatible docs
Qwen OpenAI-compatible docs
LMStudio OpenAI-compatible -
LocalAI OpenAI-compatible -
TGI (HuggingFace) OpenAI-compatible -

Format Categories

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

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 args = 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
var geminiParser = ToolCallParserFactory.GetParser(Provider.Google);
var geminiResults = geminiParser.FormatResults(results);

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 Parser Registration

// Create a custom parser
public class CustomProviderParser : IToolCallParser
{
    public Provider Provider => Provider.OpenAICompatible;
    public IReadOnlyList<ToolCall> Parse(string response) { /* ... */ }
    public IReadOnlyList<ToolCall> Parse(JsonElement element) { /* ... */ }
    public bool HasToolCalls(string response) { /* ... */ }
    public bool HasToolCalls(JsonElement element) { /* ... */ }
    public string FormatResults(IEnumerable<ToolCallResult> results) { /* ... */ }
}

// Register it
ToolCallParserFactory.RegisterParser(Provider.OpenAICompatible, new CustomProviderParser());

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

Related Projects

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

About

Unified .NET parser for LLM tool calls across 20+ providers (OpenAI, Anthropic, Google, Bedrock, Ollama, and more) with auto-detection and extensible custom parser support.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages