local-openai2anthropic
English | 中文
A lightweight proxy that bridges Anthropic and OpenAI ecosystems — run Claude SDK apps on any OpenAI-compatible backend, or use OpenAI clients directly with zero conversion overhead.
Why OA2A
- Bidirectional Protocol Conversion — Anthropic Messages API ↔ OpenAI Chat Completions API. Run Claude SDK / Claude Code on any OpenAI-compatible backend (vLLM, SGLang, cloud APIs).
- OpenAI-Native Passthrough —
POST /v1/chat/completionsforwards requests as-is with zero conversion overhead. All upstream fields preserved. - OpenAI Responses API Bridge —
POST /v1/responsesaccepts the Responses API format and translates to/v1/chat/completionsfor backends that only implement chat completions. Lets Responses SDK clients talk to any vLLM/SGLang backend. - Server-Side Web Search — Built-in Tavily / TongXiao search. Give any model internet access without client-side changes.
- Interleaved Thinking — Full support for
thinkingblocks withchat_template_kwargsandreasoning_effort. DeepSeek V4 and other reasoning models work out of the box. - Streaming, Tools & Vision — SSE real-time streaming, Claude
tool_useconversion, multi-modal image input. Full API surface coverage. - Model Name Mapping — Wildcard rules map Anthropic model names to backend models automatically.
- Daemon + Web Dashboard —
oa2a start/stop/logsfor one-command management. Built-in web UI for request monitoring.
What This Does
Three modes of operation:
| Mode | Endpoint | Use Case |
|---|---|---|
| Anthropic Proxy | POST /v1/messages |
Claude SDK / Claude Code apps talking to any OpenAI backend |
| OpenAI Passthrough | POST /v1/chat/completions |
OpenAI-native clients bypassing conversion entirely |
| Responses Bridge | POST /v1/responses |
OpenAI Responses SDK clients talking to chat-completions-only backends |
Quick Start
pip Install
pip install local-openai2anthropic
First run launches an interactive setup wizard:
oa2a start
Or run in foreground:
oa2a
Docker
docker run -d --name oa2a -p 8080:8080 \
-e OA2A_OPENAI_API_KEY=your-key \
-e OA2A_OPENAI_BASE_URL=http://host.docker.internal:8000/v1 \
dongfangzan/local-openai2anthropic:latest
Usage Example
import anthropic
client = anthropic.Anthropic(base_url="http://localhost:8080", api_key="any")
message = client.messages.create(
model="your-model",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content[0].text)
Daemon Management
oa2a start # Start in background
oa2a stop # Stop background server
oa2a restart # Restart background server
oa2a status # Check if running
oa2a logs # Show recent logs
oa2a logs -f # Follow logs in real-time
Configuration
Config file: ~/.oa2a/config.toml (auto-created)
Core Settings
| Option | Required | Default | Description |
|---|---|---|---|
openai_api_key |
Yes | — | API key for the upstream backend |
openai_base_url |
Yes | https://api.openai.com/v1 |
Upstream backend URL |
openai_org_id |
No | — | OpenAI Organization ID |
openai_project_id |
No | — | OpenAI Project ID |
host |
No | 0.0.0.0 |
Server bind address |
port |
No | 8080 |
Server port |
api_key |
No | — | Auth key for this proxy (Bearer token) |
request_timeout |
No | 300.0 |
Upstream request timeout in seconds |
log_level |
No | INFO |
DEBUG, INFO, WARNING, ERROR |
Model Name Mapping
Map Anthropic model names to backend model names with wildcard support:
default_model = "kimi-k2.5"
[[model_mapping]]
from = "sonnet"
to = "kimi-k2.5"
[[model_mapping]]
from = "*opus*"
to = "deepseek-v4"
from supports * and ? wildcards. default_model is the fallback when no rule matches.
Web Search
Supports two search providers: Tavily and TongXiao (通晓).
tavily_api_key = "tvly-xxx"
tongxiao_api_key = "xxx"
websearch_provider = "tavily" # "tavily", "tongxiao", or "both"
websearch_max_uses = 5
tavily_max_results = 5
tongxiao_max_results = 5
CORS
cors_origins = ["*"]
cors_credentials = true
cors_methods = ["*"]
cors_headers = ["*"]
API Endpoints
Anthropic-Compatible
| Method | Path | Description |
|---|---|---|
POST |
/v1/messages |
Create a message (streaming via stream: true) |
GET |
/v1/models |
List available models (proxied) |
POST |
/v1/messages/count_tokens |
Count tokens (local tiktoken estimation) |
GET |
/health |
Health check |
OpenAI-Native Passthrough
| Method | Path | Description |
|---|---|---|
POST |
/v1/chat/completions |
OpenAI-format chat completions (streaming & non-streaming) |
The passthrough endpoint forwards requests directly to the upstream — no validation, no conversion, no model mapping. All fields (including chat_template_kwargs, reasoning_effort, etc.) are preserved as-is.
OpenAI Responses API Bridge
| Method | Path | Description |
|---|---|---|
POST |
/v1/responses |
OpenAI Responses-format request, translated to chat/completions upstream |
Accepts the Responses API request shape (input, instructions, reasoning.effort, tools of type function, max_output_tokens, …) and translates it to a /v1/chat/completions call against the upstream backend. The upstream chat completion is translated back into a Responses Response object. Both streaming and non-streaming modes are supported — streaming emits the full Responses SSE event sequence (response.created → response.output_text.delta → response.completed).
Server-side web search: when the request includes a web_search / web_search_preview tool and a search provider is configured (Tavily or 通晓/TongXiao), the proxy runs the search loop locally. The web_search tool is exposed to the model as a function tool, executed via the configured provider when called, and the results are fed back so the model can answer with up-to-date information. The Responses output includes one web_search_call item per executed search. Configure search the same way as for the Anthropic path:
tavily_api_key = "tvly-xxx"
# or
tongxiao_api_key = "xxx"
websearch_provider = "tavily" # "tavily", "tongxiao", or "both"
websearch_max_uses = 5
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8080/v1", api_key="any")
resp = client.responses.create(
model="your-model",
input="Hello!",
instructions="Be concise",
)
print(resp.output_text)
Features
- Streaming — SSE real-time token streaming in both Anthropic and OpenAI modes
- Tool Calling — Claude-compatible tool use (
tool_use/tool_result) converted to OpenAI function calls - Vision — Multi-modal image input via
image_urlcontent blocks - Thinking / Reasoning — Supports
thinkingblocks withchat_template_kwargs(vLLM/SGLang) andoutput_config.efforttoreasoning_effortmapping for DeepSeek V4 - Web Search — Server-side web search via Tavily or TongXiao (通晓), usable with any model
- Model Mapping — Wildcard-based model name resolution
- API Auth — Optional Bearer token authentication for the proxy itself
- Web Dashboard — Built-in web UI at
/for monitoring request statistics - Daemon Mode — Background service management (start/stop/restart/status/logs)
Using with Claude Code
Docker (Recommended)
The repo includes a docker-compose.yml with both OA2A proxy and Claude Code pre-configured:
cat > .env << 'EOF'
OA2A_OPENAI_API_KEY=your-api-key
OA2A_OPENAI_BASE_URL=http://host.docker.internal:8000/v1
CLAUDE_MODEL=your-model-name
EOF
docker-compose up -d
docker-compose exec claude-code claude --dangerously-skip-permissions
Local Installation
Configure ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:8080",
"ANTHROPIC_API_KEY": "any",
"ANTHROPIC_MODEL": "your-model",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "your-model",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "your-model",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "your-model"
}
}
Then start the proxy (oa2a start) and launch Claude Code (claude).
Supported Backends
| Backend | Status |
|---|---|
| vLLM | Fully supported |
| SGLang | Fully supported |
| Any OpenAI-compatible API | Should work |
Ollama natively supports the Anthropic API format — point Claude SDK directly to
http://localhost:11434/v1, no proxy needed.
Development
git clone https://github.com/dongfangzan/local-openai2anthropic.git
cd local-openai2anthropic
pip install -e ".[dev]"
pytest # 445+ tests, >80% coverage
License
Apache License 2.0
Metadata
Release files for local-openai2anthropic 0.7.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| local_openai2anthropic-0.7.3.tar.gz | 5.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| local_openai2anthropic-0.7.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 6.2 MB
Release files / local_openai2anthropic-0.7.3.tar.gz
| Download URL | local_openai2anthropic-0.7.3.tar.gz |
|---|---|
| Size | 5.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c34843958c32f300bb2e55c0c2149c9b4e36cdc8dd1f28a75edd913105c27461
|
|
BLAKE2b-256 checksum How to use checksums |
c5f6e4977ac40c8732b37cb2de0c2290efcfc200fb4607657318b8448db46ae1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 30, 2026.
Transparency logRelease files / local_openai2anthropic-0.7.3-py3-none-any.whl
| Download URL | local_openai2anthropic-0.7.3-py3-none-any.whl |
|---|---|
| Size | 875.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4f2f5dcce063ea7c1b7c4c82cc3d87ba4ba1d02c191afb483a7e9c3e193c5c9b
|
|
BLAKE2b-256 checksum How to use checksums |
692b12ee7de321cca381f380db796ae1d346cbeb376be2596f00e4ef40260347
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 30, 2026.
Transparency log