Skip to main content

Python SDK for Anthropic, OpenAI, and MiniMax AI providers

Project description

motosan-ai (Python SDK)

Multi-provider Python SDK for Anthropic, OpenAI, MiniMax, and Ollama. All providers use httpx directly — no official provider SDKs required.

Installation

pip install motosan-ai
pip install "motosan-ai[anthropic]"
pip install "motosan-ai[openai]"
pip install "motosan-ai[minimax]"
pip install "motosan-ai[ollama]"
pip install "motosan-ai[full]"

Quick Start

import asyncio

from motosan_ai import Client


async def main() -> None:
    client = Client.anthropic(api_key="sk-ant-...", model="claude-sonnet-4-6")
    response = await client.chat([
        {"role": "user", "content": "Hello"},
    ])
    print(response.content)


asyncio.run(main())

Tool Use (Multi-turn)

import asyncio

from motosan_ai import Client, Message, Tool


def get_weather(city: str) -> str:
    return f"Sunny in {city}"


async def main() -> None:
    client = Client.anthropic(api_key="sk-ant-...")

    tools = [
        Tool(
            name="get_weather",
            description="Get current weather",
            input_schema={
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        )
    ]

    messages = [Message.user("What's the weather in Tokyo?")]
    response = await client.chat(messages, tools=tools)

    if response.tool_calls:
        tc = response.tool_calls[0]
        result = get_weather(tc.input["city"])

        messages += [
            Message.assistant_with_tool_calls("", response.tool_calls),
            Message.tool_result(tc.id, result),
        ]
        final = await client.chat(messages, tools=tools)
        print(final.content)


asyncio.run(main())

Streaming

import asyncio

from motosan_ai import Client, Message


async def main() -> None:
    client = Client.openai(api_key="sk-...", model="gpt-4o")

    async for event in client.stream([Message.user("Write a haiku about rain")]):
        if event.content:
            print(event.content, end="")
        if event.done:
            break


asyncio.run(main())

Sync Wrapper

from motosan_ai import Client, Message

client = Client.minimax(api_key="...")
response = client.chat_sync([Message.user("Hello from sync")])
print(response.content)

Providers

Anthropic

from motosan_ai import Client

client = Client.anthropic(api_key="sk-ant-...", model="claude-sonnet-4-6")

OpenAI

from motosan_ai import Client

client = Client.openai(api_key="sk-...", model="gpt-4o")

MiniMax

from motosan_ai import Client

client = Client.minimax(api_key="...", model="MiniMax-M1")

Ollama

from motosan_ai import Client

# OpenAI-compatible mode (default)
client = Client.ollama(model="llama3.2")

# Native Ollama API mode (supports think/keep_alive/num_ctx)
client = Client.ollama(model="llama3.2", ollama_native=True, ollama_think=True)

Anthropic Auth Matrix

  • sk-ant-api* or regular Anthropic API key → x-api-key header
  • sk-ant-oat01* OAuth token → OAuth mode:
    • Authorization: Bearer <token> header (via httpx directly)
    • anthropic-beta: claude-code-20250219,oauth-2025-04-20,... headers
    • user-agent: claude-code/<version> + x-app: cli identity headers
    • System prompt sent as array of blocks (prefix + user system)
    • Claude Code system prompt prefix auto-injected
    • chat() auto-redirects to stream() and collects result (including tool_calls)

The SDK auto-detects token type by prefix — pass either into Client.anthropic(api_key=...).

from motosan_ai import Client

# Standard API key
client = Client.anthropic(api_key="sk-ant-api03-...")

# OAuth token (auto-detected, same interface)
client = Client.anthropic(api_key="sk-ant-oat01-...")

HTTP Client

All providers use httpx directly — no official provider SDKs (anthropic, openai) required. This keeps the dependency tree minimal and gives full control over auth, headers, and SSE parsing.

Requirements

  • Python 3.11+
  • One provider API key:
    • ANTHROPIC_API_KEY (standard API key or OAuth token)
    • OPENAI_API_KEY
    • MINIMAX_API_KEY
    • Ollama: no key needed (local)

Testing

# Unit tests (mock, no API needed)
uv run pytest sdks/python/tests/ -q --ignore=sdks/python/tests/integration/

# Live integration tests (requires ANTHROPIC_API_KEY)
ANTHROPIC_API_KEY=... uv run pytest sdks/python/tests/integration/test_anthropic_live.py -v

Publishing

Automated via publish-python.yml on python-v* tag push → PyPI.

# Tag and push to trigger publish
git tag -a python-vX.Y.Z -m "python-vX.Y.Z — summary"
git push origin python-vX.Y.Z

# Manual (emergency)
uv build --out-dir dist && uv publish dist/*

Rust and Python SDKs are versioned independently.

Development

uv sync --extra full --extra dev
uv run ruff check motosan_ai/
uv run pytest -q

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

motosan_ai-0.4.2.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

motosan_ai-0.4.2-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file motosan_ai-0.4.2.tar.gz.

File metadata

  • Download URL: motosan_ai-0.4.2.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for motosan_ai-0.4.2.tar.gz
Algorithm Hash digest
SHA256 fa44983895293ac3b36548642573d36edf2fa31393db7a8fb067e629f93b7232
MD5 3f18921fd1538201d50d73b09b91f54b
BLAKE2b-256 12821d1f85ce257232b5113d9aabc7e7fd44f829ca5990a7198ca1d58ea4fcb4

See more details on using hashes here.

File details

Details for the file motosan_ai-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: motosan_ai-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for motosan_ai-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4d4e54b1bce27b610c19b62f18c1b2360636491e754154bc05dcfc6f85916246
MD5 acdc821f6a59cf0e956b9114ea0e7739
BLAKE2b-256 1e9e38eb66c91f7d29b7b47ce42c079ac872dd00a8ed8c6fb743aa2e51a2b288

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page