How to Add a New OpenAI‑Compatible Provider to DeepSeek‑Reasonix: A Complete Configuration Guide

Adding a new OpenAI‑compatible provider to DeepSeek‑Reasonix requires only a TOML configuration entry with kind = "openai", as the generic provider implementation automatically handles request serialization, authentication, and streaming for any endpoint that follows the OpenAI API specification.

DeepSeek‑Reasonix treats every OpenAI‑compatible endpoint as a first‑class provider that is described purely by configuration. The actual request handling lives in the self‑registering OpenAI provider implementation (internal/provider/openai/openai.go), which means you can integrate custom proxies, local inference servers, or third‑party APIs without writing a single line of Go code.

Understanding the Provider Registration Architecture

Reasonix uses a factory registration pattern that decouples provider discovery from implementation details. When the application starts, the openai package initializes itself and advertises its capability to handle OpenAI‑compatible wire protocols.

In internal/provider/openai/openai.go, the init() function registers the factory under the canonical name "openai":

// internal/provider/openai/openai.go
func init() {
    provider.Register("openai", New)   // ← registers the factory
}

This registration allows the configuration system in internal/config/config.go to instantiate the correct provider whenever it encounters a provider entry with kind = "openai". The helper function isOpenAIProviderKind (line 2384) specifically checks for this identifier to route configuration data to the appropriate factory.

Configuration‑Only Setup: Defining Your Provider in TOML

To add a new OpenAI‑compatible provider, create or edit your Reasonix configuration file (typically ~/.config/reasonix/reasonix.toml) and append a new [[providers]] block. The system requires only two fields—base_url and model—while remaining fields are optional.


# ~/.config/reasonix/reasonix.toml

[[providers]]
name = "my-openai-proxy"          # Friendly identifier used on the CLI

kind = "openai"                   # ← Required: triggers OpenAI provider logic

base_url = "https://proxy.example.com/v1"   # Root of the OpenAI‑compatible API

model = "gpt-4o-mini"             # Model name advertised by the endpoint

api_key = "sk-xxxxxxxxxxxxxxxxxxxx"          # Optional: can also use ENV variable

# Optional extras controlling reasoning effort and vision capabilities

extra = { 
    effort = "high",               # low | medium | high (or "auto")

    vision = true,                # Enable image input if supported

    vision_detail = "high"        # "low" or "high", defaults to auto

}

The TOML parser materializes each entry into a provider.Config struct. When kind equals "openai", the configuration loader passes this struct to the New factory function in internal/provider/openai/openai.go.

How the OpenAI Provider Factory Validates and Builds Clients

The New function (lines 44‑101 in internal/provider/openai/openai.go) constructs a concrete HTTP client from the resolved configuration. It performs strict validation to ensure the endpoint is usable:

  • Base URL validation (line 46): Verifies cfg.BaseURL is present and well‑formed.
  • Model validation (line 49): Ensures cfg.Model is non‑empty.
  • Extra options parsing (lines 56‑68): Normalizes fields like effort, vision, and vision_detail from the cfg.Extra map.
  • Reasoning protocol handling (lines 71‑101): Configures reasoning effort parameters that DeepSeek‑Reasonix uses to control chain‑of‑thought depth.

If validation passes, the factory returns a client instance that implements the provider.Provider interface, exposing methods like Stream and Chat. The rest of the system interacts with this client through the generic interface, meaning no downstream code changes are required when you add a new provider.

Runtime Discovery and Usage

Once the configuration entry exists, Reasonix automatically detects the provider at runtime. The desktop UI can probe the endpoint for available models using the FetchProviderModels function in desktop/settings_app.go (lines 1240‑1255), which calls the provider’s /models endpoint.

Command Line Usage

Select your new provider by its friendly name using the --provider flag:

reasonix --provider my-openai-proxy "Explain quantum entanglement in simple terms."

The CLI parses the flag, looks up the matching ProviderEntry via the configuration system, and routes the request to the OpenAI‑compatible client.

Programmatic Usage

If you embed Reasonix as a library, resolve the provider by name and stream requests directly:

import (
    "context"
    "fmt"
    "reasonix/internal/provider"
)

func main() {
    // Resolve the provider by name – identical logic to the CLI
    prov, err := provider.Resolve("my-openai-proxy")
    if err != nil {
        panic(err)
    }

    // Build a request (see provider.Request for all fields)
    req := provider.Request{
        Prompt: "Write a haiku about compiled languages.",
    }

    // Stream the response
    ch, err := prov.Stream(context.Background(), req)
    if err != nil {
        panic(err)
    }
    for chunk := range ch {
        fmt.Print(chunk.Text)
    }
}

Summary

  • Registration happens automatically: The init() function in internal/provider/openai/openai.go registers the factory under the name "openai" using provider.Register("openai", New).
  • Configuration is the only requirement: Add a [[providers]] block with kind = "openai", base_url, and model to reasonix.toml.
  • Validation occurs at startup: The New factory validates required fields (lines 44‑53) and parses optional extras like reasoning effort (lines 71‑101).
  • Discovery is built‑in: The desktop UI probes the /models endpoint via FetchProviderModels in desktop/settings_app.go (lines 1240‑1255).
  • Usage is seamless: Reference the provider by its name in CLI flags or use provider.Resolve() programmatically.

Frequently Asked Questions

Do I need to modify the Go source code to add a custom OpenAI endpoint?

No. DeepSeek‑Reasonix treats OpenAI‑compatible endpoints as configuration‑only providers. As long as your endpoint speaks the standard OpenAI chat completions protocol, you only need to add a TOML entry with kind = "openai". The generic implementation in internal/provider/openai/openai.go handles all request formatting and authentication.

What configuration fields are required for an OpenAI‑compatible provider?

The mandatory fields are base_url (the root URL of the API) and model (the identifier of the model to use). These are validated in the New factory function at lines 46 and 49 of internal/provider/openai/openai.go. The api_key is optional and can be omitted if your endpoint does not require authentication or if you prefer to pass it via environment variables.

How does Reasonix distinguish between native DeepSeek and OpenAI‑compatible providers?

The configuration system uses the isOpenAIProviderKind helper function at line 2384 of internal/config/config.go to inspect the kind field. When kind equals "openai", the system instantiates the provider using the factory registered in internal/provider/openai/openai.go. This allows Reasonix to support multiple protocol families simultaneously while using a unified internal interface.

Can I use environment variables instead of hardcoding the API key in the TOML file?

Yes. While you can specify api_key directly in the TOML provider block, Reasonix also respects environment variables for sensitive configuration. The configuration parser in internal/config/config.go resolves variables before constructing the provider.Config, allowing you to keep secrets out of version-controlled configuration files.

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 →