# How AxonHub Implements Any SDK to Any Model Translation

> Discover how AxonHub enables Any SDK to Any Model translation by normalizing requests to a generic agent Message format and using provider specific conversion layers. Unlock seamless LLM integration.

- Repository: [Loop/axonhub](https://github.com/looplj/axonhub)
- Tags: how-to-guide
- Published: 2026-03-06

---

**AxonHub decouples client SDKs from LLM models by normalizing all requests into a generic `agent.Message` format and using provider-specific conversion layers to translate between the unified interface and native vendor SDKs.**

The `looplj/axonhub` repository solves the fragmentation problem in AI development by enabling any SDK to any model translation through a unified abstraction layer. This architecture allows developers to switch between OpenAI, Anthropic, Vertex, and other providers without changing application code, as every vendor implements the same `agent.Provider` contract.

## The Three-Layer Translation Architecture

### Generic Data Model

At the core of the translation system lies a vendor-agnostic data model defined in [`axon/agent/message.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/message.go). This package declares universal types such as `agent.Message`, `agent.ToolDefinition`, and `agent.Response` that capture concepts common to all LLM APIs—roles (system, user, assistant, tool), content parts (text, images, tool calls), and metadata. By flattening vendor-specific extensions into this normalized structure, AxonHub ensures that upstream code remains agnostic to the underlying model provider.

### Provider Interface Contract

The translation contract is enforced by the `agent.Provider` interface declared in [`axon/agent/provider.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/provider.go). Every LLM vendor must implement two methods: `Chat(ctx context.Context, model string, tools []ToolDefinition, messages []Message) (*Response, error)` and `ChatStream(ctx context.Context, model string, tools []ToolDefinition, messages []Message) (StreamIterator, error)`. This strict interface guarantees that any SDK generating a `[]agent.Message` slice can invoke any provider without modification, achieving true any SDK to any model translation.

### Bidirectional Conversion Layer

Each provider package contains a conversion layer that maps between the generic agent types and the vendor's native SDK structs. For example, [`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go) exports `convertMessages` to transform `[]agent.Message` into Anthropic's `MessageParam` types, and `convertResponse` to translate Anthropic's `Message` back into `agent.Response`. These functions handle vendor-specific quirks—such as Anthropic's separate system prompt field or OpenAI's function calling format—while presenting a uniform interface to the rest of the system.

## Step-by-Step Translation Flow

The any SDK to any model translation process follows a rigorous seven-step pipeline:

1. **Client builds generic request.** Application code constructs a `[]agent.Message` slice using the unified types from [`axon/agent/message.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/message.go), specifying roles and content without considering the target vendor.

2. **Hub resolves provider implementation.** Based on the model name (e.g., `"claude-3-sonnet-20240229"`), AxonHub selects the corresponding `agent.Provider` implementation. The provider may be wrapped by `reloadable.Provider` from [`axon/provider/reloadable/reloadable.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/reloadable/reloadable.go) to enable runtime swapping.

3. **Provider converts to vendor format.** The provider's `Chat` method invokes conversion functions such as `convertMessages` in [`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go) to generate the vendor-specific request payload.

4. **Native SDK executes request.** The generated struct (e.g., Anthropic's `MessageParam`) is passed to the vendor's official Go SDK, which handles HTTP transport and authentication.

5. **Vendor response is captured.** The native SDK returns its proprietary response type (e.g., `anthropic.Message`), which the provider receives in its raw form.

6. **Provider converts to generic response.** The provider calls `convertResponse` to map the vendor-specific payload back into `agent.Response`, normalizing message roles, content parts, and tool calls.

7. **Hub returns unified result.** The caller receives a standard `agent.Response` containing `[]agent.Message`, which can be processed by any downstream logic regardless of which LLM generated it.

For streaming workloads, providers implement `ChatStream`, converting each SSE event or chunk into the unified `agent.StreamEvent` type defined in [`axon/agent/provider.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/provider.go).

## Runtime Provider Swapping with Reloadable Providers

AxonHub's any SDK to any model translation includes a sophisticated runtime flexibility mechanism via `reloadable.Provider` in [`axon/provider/reloadable/reloadable.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/reloadable/reloadable.go). This wrapper implements the same `agent.Provider` interface while delegating to an underlying provider that can be swapped at runtime. When configuration changes or a new model version becomes available, the hub can update the provider instance without restarting the application or breaking existing client connections. This capability ensures that production systems can migrate between LLM vendors or upgrade model versions with zero downtime, all while maintaining the unified translation contract.

## Practical Implementation: Calling Any Model Through the Unified API

The following example demonstrates how application code uses the any SDK to any model translation layer to invoke an Anthropic model. The identical pattern works for OpenAI, Vertex, or any other supported provider by simply changing the provider constructor.

```go
package main

import (
	"context"
	"log"

	"github.com/looplj/axonhub/axon/agent"
	"github.com/looplj/axonhub/axon/provider/anthropic"
)

func main() {
	// Build a generic request using unified types
	messages := []agent.Message{
		{
			Role:    agent.RoleUser,
			Content: &agent.Content{Text: strPtr("Explain quantum tunnelling in two sentences.")},
		},
	}

	// Initialize the provider (swap anthropic.New for openai.New or vertex.New for any SDK to any model translation)
	prov := anthropic.New("<YOUR_ANTHROPIC_API_KEY>") // implements agent.Provider

	// Execute Chat through the unified interface
	resp, err := prov.Chat(context.Background(), "claude-3-sonnet-20240229", nil, messages)
	if err != nil {
		log.Fatalf("chat failed: %v", err)
	}

	// Process the normalized response
	for _, msg := range resp.Messages {
		if msg.Content != nil && msg.Content.Text != nil {
			log.Printf("Assistant: %s", *msg.Content.Text)
		}
	}
}

func strPtr(s string) *string { return &s }

```

This example illustrates the core principle of AxonHub's translation layer: once messages are normalized into `[]agent.Message`, the same code path supports any LLM vendor without modification.

## Key Source Files for Any SDK to Any Model Translation

Understanding the translation mechanism requires familiarity with these critical files in the `looplj/axonhub` repository:

- **[`axon/agent/message.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/message.go)** – Defines the generic `Message`, `Content`, `ToolDefinition`, and `Response` types that normalize vendor-specific structures.

- **[`axon/agent/provider.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/provider.go)** – Declares the `Provider` interface contract with `Chat` and `ChatStream` methods, along with the `StreamEvent` type for unified streaming.

- **[`axon/provider/reloadable/reloadable.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/reloadable/reloadable.go)** – Implements the `reloadable.Provider` wrapper that enables runtime swapping of provider implementations without breaking the translation contract.

- **[`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go)** – Contains `convertMessages` and `convertResponse` functions demonstrating bidirectional translation between generic agent types and Anthropic's SDK-specific structs.

- **[`axon/provider/anthropic/provider.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/provider.go)** – Shows the concrete implementation of `agent.Provider` for Anthropic, including how it invokes the conversion layer and native SDK.

These files collectively demonstrate how AxonHub achieves any SDK to any model translation through strict interface contracts and bidirectional conversion mappings.

## Summary

- **AxonHub** enables any SDK to any model translation by normalizing all LLM interactions through the `agent.Provider` interface and generic `agent.Message` types.
- **Bidirectional conversion** functions in each provider package (e.g., `convertMessages` and `convertResponse` in [`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go)) map between vendor-specific SDK structs and the unified data model.
- **Runtime flexibility** is achieved through `reloadable.Provider` in [`axon/provider/reloadable/reloadable.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/reloadable/reloadable.go), allowing hot-swapping of LLM implementations without application restarts.
- **Unified streaming** support via `ChatStream` methods and `agent.StreamEvent` types ensures consistent behavior across both synchronous and asynchronous model interactions.

## Frequently Asked Questions

### How does AxonHub handle vendor-specific features like Anthropic's system prompts or OpenAI's function calling?

AxonHub handles vendor-specific features through **bidirectional conversion logic** in each provider's [`convert.go`](https://github.com/looplj/axonhub/blob/main/convert.go) file. For example, [`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go) extracts the system prompt from the generic `[]agent.Message` slice and places it in Anthropic's dedicated `System` field, while `convertResponse` maps Anthropic's content blocks back to the unified `agent.Content` structure. This approach allows the generic model to capture common patterns while provider-specific code handles unique vendor implementations.

### Can I switch between LLM providers without restarting my application?

Yes, AxonHub supports **runtime provider swapping** through the `reloadable.Provider` implementation in [`axon/provider/reloadable/reloadable.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/reloadable/reloadable.go). This wrapper implements the same `agent.Provider` interface as concrete providers like Anthropic or OpenAI, but delegates to an underlying provider that can be updated atomically. When configuration changes or you need to failover to a different model, the hub updates the underlying provider instance while maintaining the same interface contract, enabling zero-downtime migrations between LLM vendors.

### What is the performance impact of the translation layer?

The translation layer adds **minimal overhead** consisting primarily of struct-to-struct memory mapping and type conversions. The generic `agent.Message` types in [`axon/agent/message.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/message.go) are designed to align closely with common LLM API patterns, avoiding expensive transformations. Conversion functions like `convertMessages` in [`axon/provider/anthropic/convert.go`](https://github.com/looplj/axonhub/blob/main/axon/provider/anthropic/convert.go) perform straightforward field mappings without network I/O or serialization overhead beyond what the underlying vendor SDK already requires. For high-throughput applications, the `reloadable.Provider` allows hot-swapping to optimized provider implementations without code changes.

### Does AxonHub support streaming responses from all providers?

Yes, AxonHub provides **unified streaming support** through the `ChatStream` method defined in [`axon/agent/provider.go`](https://github.com/looplj/axonhub/blob/main/axon/agent/provider.go). Each provider implementation converts native streaming events—such as Server-Sent Events (SSE) from OpenAI or Anthropic's streaming chunks—into the generic `agent.StreamEvent` type. This normalization ensures that client code can process streaming responses using a single iterator pattern regardless of the underlying LLM vendor, with the provider-specific conversion handling protocol differences transparently.