OpenAI vs Anthropic Provider Kinds in DeepSeek-Reasonix: API Differences Explained

The openai and anthropic provider kinds in esengine/DeepSeek-Reasonix implement different external API protocols—OpenAI-compatible chat completions versus Anthropic's Claude API—while exposing a unified internal interface through service-specific request translation, token accounting, and error handling.

DeepSeek-Reasonix abstracts multiple large language model backends through a pluggable provider system. Understanding the differences between the openai and anthropic provider kinds is essential for configuring the correct API endpoints, model names, and message formats, as each kind translates internal representations to distinct external schemas.

Provider Registration and Kind Identification

The fundamental distinction begins at the registration level. In internal/provider/openai/openai.go, the package self-registers under the kind "openai" using the registry pattern:

provider.Register("openai", New)

Conversely, the Anthropic provider registers under the kind "anthropic" in its corresponding initialization file. The configuration validator in internal/diagnose.go explicitly recognizes both kinds as valid entries, rejecting any provider configuration that does not specify either "openai" or "anthropic" as the Kind field.

API Endpoint and Protocol Handling

Each provider kind targets a different base URL and protocol specification. The openai provider defaults to https://api.openai.com/v1 and implements the standard OpenAI chat completions format, detecting the hostname using strings.EqualFold(u.Hostname(), "api.openai.com") in the host resolution logic.

The anthropic provider targets https://api.anthropic.com/v1 and implements Anthropic's native message format. While both providers accept a custom BaseURL for proxy or gateway scenarios, the internal protocol negotiation differs: the OpenAI provider sets protocol = "openai" whereas the Anthropic provider uses protocol = "anthropic" to determine message serialization strategy and capability mapping.

Message Format and Schema Translation

Despite sharing an internal Message representation, the providers translate to service-specific schemas. The openai provider converts messages to the standard OpenAI JSON format with fields like role, content, and tool_calls, handling OpenAI-style function calling and streaming deltas.

The anthropic provider converts the same internal structures to Anthropic's request schema, which uses distinct field naming for tool interactions—specifically tool_use and tool_result blocks that differ in nesting and structure from OpenAI's format. This translation layer ensures that tool calling and multi-turn conversations work correctly with Claude models while maintaining API consistency internally.

Token Accounting and Usage Metrics

Token counting conventions differ significantly between the two APIs. The openai provider expects and normalizes OpenAI's prompt_tokens, completion_tokens, and total_tokens fields, mapping them to internal accounting structures.

The anthropic provider processes Anthropic's input_tokens and output_tokens fields, performing the same normalization but accounting for the different terminology and granularity that Anthropic's API returns. Both providers ultimately expose unified token counts to the application layer, but the underlying field extraction reflects each service's native terminology.

Error Handling and Streaming Implementation

Error prefixes help identify the source provider during debugging. The OpenAI provider emits errors prefixed with openai:, such as openai: network: ..., while the Anthropic provider uses the anthropic: prefix.

Both providers support streaming responses, but implementation details vary. The openai provider implements Server-Sent Events (SSE) parsing compatible with OpenAI's streaming format, yielding partial Delta objects. The anthropic provider implements a separate streaming loop that respects Anthropic's chunk format and stream boolean parameters. While the internal consumer receives the same streaming interface, the underlying byte parsing accommodates each service's specific server-sent event structure.

Configuration Examples

To configure the OpenAI provider for GPT-4 or compatible models:

cfg := provider.Config{
    Name:    "openai",
    Kind:    "openai",
    APIKey:  "sk-your-openai-key",
    BaseURL: "https://api.openai.com/v1",
    Model:   "gpt-4o",
}
client := provider.New(cfg)

For Claude models via the Anthropic provider:

cfg := provider.Config{
    Name:    "anthropic",
    Kind:    "anthropic",
    APIKey:  "anth-your-api-key",
    BaseURL: "https://api.anthropic.com/v1",
    Model:   "claude-3-opus-20240229",
}
client := provider.New(cfg)

Both configurations use the same constructor pattern but require the correct Kind field to instantiate the appropriate protocol handler defined in internal/provider/openai/openai.go or internal/provider/anthropic/anthropic.go. After initialization, both clients expose identical Chat methods, hiding the underlying API differences.

Summary

  • The openai provider implements the OpenAI-compatible chat completions protocol, while anthropic implements Anthropic's native Claude API.
  • Both register distinct provider kinds in the internal registry and validate against supported kinds in internal/diagnose.go.
  • Message translation differs: OpenAI uses tool_calls format, while Anthropic uses tool_use and tool_result blocks.
  • Token fields vary: OpenAI uses prompt_tokens/completion_tokens; Anthropic uses input_tokens/output_tokens.
  • Error prefixes distinguish providers: openai: versus anthropic:.
  • Streaming implementations handle service-specific SSE formats but expose a unified interface to the application.
  • Configuration requires matching the Kind field to the target API, with both supporting custom BaseURL values for proxy deployments.

Frequently Asked Questions

Can I use an OpenAI-compatible proxy with the anthropic provider?

No. The anthropic provider specifically implements Anthropic's message schema and token accounting. While both providers accept custom BaseURL values, the anthropic provider expects Anthropic-specific response structures including input_tokens and tool_use blocks. Using an OpenAI-compatible proxy requires the openai provider kind, which understands the OpenAI chat completions format and translates requests accordingly.

How does token counting differ between the two providers?

The OpenAI provider extracts prompt_tokens and completion_tokens from responses and calculates total_tokens accordingly. The Anthropic provider extracts input_tokens and output_tokens directly from Anthropic's usage fields. Both normalize these values to the internal accounting format, but the source fields and calculation methods reflect each API's native terminology as implemented in internal/provider/provider.go.

Which provider kind should I use for Claude models?

Use the anthropic provider kind for all Claude models (Claude 2, Claude 3 Opus, Sonnet, etc.). This ensures correct message formatting, proper handling of Anthropic's extended thinking capabilities, and accurate token counting. Attempting to use Claude models with the openai provider kind will result in schema mismatches and API errors because the request serialization logic differs between the two implementations.

Are tool calling capabilities identical across both provider kinds?

While both providers support function calling, the internal representation differs significantly. The openai provider handles OpenAI-style tool_calls and function objects, while the anthropic provider manages Anthropic's tool_use and tool_result message types. DeepSeek-Reasonix abstracts these differences automatically, but the underlying API structures remain distinct as implemented in internal/provider/openai/openai.go and internal/provider/anthropic/anthropic.go.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →