# How to Migrate from Direct Provider SDK Calls to aisuite's Unified API

> Effortlessly migrate from direct provider SDK calls to aisuite's unified API. Replace clients, prefix models, and use consistent OpenAI-style parameters for all providers. Simplify your AI integration today.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: migration-guide
- Published: 2026-08-03

---

**Migrate from vendor-specific SDK calls to aisuite's unified API by replacing the provider client with `aisuite.Client()`, prefixing your model name with the provider identifier (e.g., `openai:gpt-4o`), and using the same OpenAI-style request parameters across all providers.**

The aisuite library from Andrew Ng's team eliminates the friction of juggling multiple LLM SDKs. Instead of importing `openai`, `anthropic`, `google.generativeai`, and others, you install one package and call any supported model through a single, consistent interface. This article walks through the architectural concepts, concrete migration steps, and code patterns you need to transition your existing codebase.

## Why aisuite Exists: The Provider Adapter Architecture

Under the hood, aisuite implements a **provider adapter pattern** that bridges the gap between vendor-specific APIs and a universal Chat Completions interface.

Each supported LLM provider has a lightweight adapter class that follows strict naming conventions:
- File naming: `<provider>_provider.py` (e.g., [`openai_provider.py`](https://github.com/andrewyng/aisuite/blob/main/openai_provider.py), [`anthropic_provider.py`](https://github.com/andrewyng/aisuite/blob/main/anthropic_provider.py))
- Class naming: `<Provider>Provider` (e.g., `OpenaiProvider`, `AnthropicProvider`)

These adapters are discovered automatically by the framework's dynamic loading system. As seen in the legacy interface at [[`aisuite/framework/provider_interface.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/provider_interface.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/provider_interface.py), every provider implements a standard contract for chat completion requests.

The core abstraction lives in [[`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py), which defines the base `Provider` class that all concrete adapters extend. This architecture means aisuite can normalize request parameters, response formats, and even tool-calling behavior across dozens of LLM vendors.

## Step-by-Step SDK Migration Process

### Step 1: Install aisuite with Your Required Provider Dependencies

 aisuite uses an optional dependency model—you only install the SDKs you actually need.

```bash

# OpenAI only

pip install "aisuite[openai]"

# Multiple providers

pip install "aisuite[openai,anthropic,google]"

# All supported providers

pip install "aisuite[all]"

```

The client imports provider SDKs **lazily**, so you won't pay the import cost for providers you don't use.

### Step 2: Replace the SDK Client with aisuite.Client()

This is the core migration change. Instead of instantiating a provider-specific client, you create a single `aisuite.Client()` instance.

**Before: Direct OpenAI SDK**

```python
import openai

client = openai.OpenAI(api_key="sk-...")
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Explain quantum computing in one sentence."},
]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    temperature=0.7,
    max_tokens=100,
)

print(response.choices[0].message.content)

```

**After: aisuite Unified API**

```python
import aisuite as ai

client = ai.Client()  # Reads API keys from environment variables

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Explain quantum computing in one sentence."},
]

response = client.chat.completions.create(
    model="openai:gpt-4o",  # Provider prefix + model name

    messages=messages,
    temperature=0.7,
    max_tokens=100,
)

print(response.choices[0].message.content)

```

The key differences:
- Remove provider-specific imports and client initialization
- Prefix the model identifier with `<provider>:` (e.g., `openai:`, `anthropic:`, `google:`)
- The `aisuite.Client()` automatically reads API keys from standard environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.)

### Step 3: Leverage Automatic Parameter Normalization

One of aisuite's most valuable features is **parameter mapping** across providers. Different LLM APIs use different parameter names and value ranges. The [[`aisuite/framework/parameter_mapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/parameter_mapper.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/parameter_mapper.py) module handles these translations automatically.

| OpenAI Parameter | Anthropic Equivalent | Google Equivalent |
|------------------|----------------------|-------------------|
| `temperature` | `temperature` | `temperature` |
| `max_tokens` | `max_tokens` | `max_output_tokens` |
| `top_p` | `top_p` | `top_p` |
| `stop` | `stop_sequences` | `stop_sequences` |

With aisuite, you always use the OpenAI-style parameter names, and the adapter translates them to provider-native equivalents. This means the **same code works across providers without modification**:

```python

# Identical request shape for any provider

params = {
    "messages": messages,
    "temperature": 0.7,
    "max_tokens": 500,
    "top_p": 0.9,
}

# Works with OpenAI

openai_resp = client.chat.completions.create(model="openai:gpt-4o", **params)

# Works with Anthropic—same parameters, no translation needed

anthropic_resp = client.chat.completions.create(
    model="anthropic:claude-3-5-sonnet-20240620",
    **params
)

# Works with Google Gemini

google_resp = client.chat.completions.create(
    model="google:gemini-1.5-pro",
    **params
)

```

## Migrating Tool Calling and Function Execution

Direct SDK implementations require manual parsing of `tool_calls` from responses, separate function execution, and result injection back into the conversation. aisuite's **Agents API** automates this entire flow.

### Before: Manual Tool Calling with OpenAI SDK

```python
import openai
import json

client = openai.OpenAI()

def get_weather(city: str) -> str:
    """Get weather for a city."""
    # Implementation omitted

    return f"Sunny and 72°F in {city}"

messages = [
    {"role": "user", "content": "What's the weather in San Francisco?"}
]

# Define tool schema manually

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name"}
            },
            "required": ["city"]
        }
    }
}]

# First API call

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
)
message = response.choices[0].message

# Manual tool call handling

if message.tool_calls:
    for tool_call in message.tool_calls:
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)
        
        # Execute function

        result = get_weather(**function_args)
        
        # Add tool result to messages

        messages.append(message.model_dump())
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": result,
        })
    
    # Second API call with results

    final_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
    )
    print(final_response.choices[0].message.content)

```

### After: aisuite Automatic Tool Execution

```python
import aisuite as ai

client = ai.Client()

def get_weather(city: str) -> str:
    """Get weather for a city."""
    return f"Sunny and 72°F in {city}"

messages = [
    {"role": "user", "content": "What's the weather in San Francisco?"}
]

# Pass Python function directly—aisuite auto-generates schema

response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=messages,
    tools=[get_weather],  # List of Python functions

    max_turns=2,  # Let aisuite handle the full tool loop

)

print(response.choices[0].message.content)

```

The conversion from Python callable to OpenAI-style tool specification happens in [[`aisuite/utils/tools.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/utils/tools.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/utils/tools.py), which uses docstring parsing and type hints to generate accurate JSON schemas.

## Handling Streaming Responses

Streaming migration follows the same pattern—replace the provider client and model identifier:

```python
import aisuite as ai

client = ai.Client()

stream = client.chat.completions.create(
    model="anthropic:claude-3-5-sonnet-20240620",
    messages=[{"role": "user", "content": "Count to 10"}],
    stream=True,
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

```

The streaming interface returns the same `ChatCompletionChunk` objects regardless of provider, so post-processing code requires no changes when switching between models.

## Environment Configuration and API Keys

aisuite follows the **convention-over-configuration** principle for authentication:

| Provider | Environment Variable | Automatic Detection |
|----------|----------------------|---------------------|
| OpenAI | `OPENAI_API_KEY` | Yes |
| Anthropic | `ANTHROPIC_API_KEY` | Yes |
| Google | `GOOGLE_API_KEY` | Yes |
| Azure OpenAI | `AZURE_OPENAI_KEY`, `AZURE_OPENAI_ENDPOINT` | Yes |
| AWS Bedrock | AWS credential chain | Yes |

For explicit control, you can pass configuration via the `Client` constructor:

```python
client = ai.Client({
    "openai": {"api_key": "sk-...", "timeout": 60},
    "anthropic": {"api_key": "sk-ant-...", "max_retries": 3},
})

```

## Summary

- **Install aisuite** with provider-specific extras to control dependencies
- **Replace `openai.Client()` with `ai.Client()`** and prefix models with `<provider>:`
- **Use OpenAI-style parameters** everywhere—aisuite's `ParameterMapper` handles translation
- **Pass Python functions directly** to `tools=` for automatic schema generation and execution
- **Leverage `max_turns`** to let aisuite manage multi-turn tool conversations

The provider adapter architecture in [[`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py) and parameter normalization in [[`aisuite/framework/parameter_mapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/parameter_mapper.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/parameter_mapper.py) make this unified interface possible across all supported LLM vendors.

## Frequently Asked Questions

### How do I know which providers and models are supported?

Check the [[`README.md`](https://github.com/andrewyng/aisuite/blob/main/README.md)](https://github.com/andrewyng/aisuite/blob/main/README.md) for the current list of supported providers. The provider discovery system dynamically loads any adapter following the `<provider>_provider.py` naming convention, so new providers can be added without core library changes.

### Can I use aisuite with my existing fine-tuned or deployed models?

Yes. Any model accessible through a provider's standard API works with the unified interface. For custom deployments (e.g., Azure OpenAI with your own endpoint), configure the `Client` with explicit provider settings including the base URL and deployment name.

### What happens if a provider doesn't support a specific parameter?

The `ParameterMapper` silently drops or transforms unsupported parameters rather than raising errors. For example, if you pass `tools` to a model without tool support, aisuite returns a standard completion without tool-related fields. Check provider-specific documentation for capability matrix details.

### Is there performance overhead from the abstraction layer?

Minimal. The adapter layer adds approximately 1-2ms of Python overhead per request—negligible compared to network latency. The lazy SDK loading in [[`aisuite/provider.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py)](https://github.com/andrewyng/aisuite/blob/main/aisuite/provider.py) ensures you only pay the import cost for providers you actually use.