Standalone translating gateway for ALCF inference endpoints (OpenAI chat/responses, Anthropic messages)
Project description
ALCF-proxy
📖 Full documentation: alcf-proxy.readthedocs.io
A standalone, cross-platform translating gateway for ALCF inference endpoints. Run one local proxy and point any OpenAI- or Anthropic-style coding CLI at it — Codex, Claude Code, Aider, OpenCode, and more — without each tool needing to know about ALCF's auth or wire format.
Inspired by argo-proxy, but the upstream is ALCF's public Bearer-authenticated gateway (not ANL ARGO), and the proxy manages ALCF's rotating token for you.
What it does
- Speaks 3 client formats on one instance:
/v1/chat/completions— OpenAI SDK, Aider, OpenCode/v1/responses— Codex CLI/v1/messages— Claude Code
- Translates every request to ALCF's streaming
chat/completionsupstream via llm-rosetta, and translates the streamed reply back to the client's format — real token-by-token streaming. - Manages the ALCF token: authenticates via Globus (built in — no external script needed), injects the token as a Bearer header, and refreshes automatically when it nears its ~48h expiry. Clients just use a dummy key.
- Endpoint auto-failover: if a cluster returns 503 / is under maintenance, the proxy advances to the next configured endpoint (remapping the per-endpoint model id) and sticks to the one that works.
Prerequisites
- Python ≥ 3.10. All auth is built in (via
globus-sdk, installed automatically); you do not need ALCF'sinference_auth_token.py. - First-time login (once):
alcf-proxy auth login— opens a browser for Globus OAuth and stores the token in globus-sdk's standard per-platform location (resolved correctly on Linux/macOS/Windows; check it any time withalcf-proxy auth status). The refresh token then lasts months.
Install
pip install alcf-proxy
Or run without installing, using uv:
uvx alcf-proxy serve
From source (development)
git clone https://github.com/cshjin/alcf-proxy
cd alcf-proxy
pip install -e . # editable install
# or: pip install -e ".[dev]" # with test/build tooling
uvx --from . alcf-proxy serve # one-shot run from a checkout
Platform notes
- Linux / macOS / Windows are all supported (pure Python; config paths resolved via
platformdirs). Config lives at~/.config/alcf-proxy/config.yaml(Linux),~/Library/Application Support/alcf-proxy/config.yaml(macOS), or%APPDATA%\alcf-proxy\config.yaml(Windows). - The token is stored by
globus-sdkin its standard per-platform app-data dir (on Windows this is under%LOCALAPPDATA%, resolved automatically — no hard-coded~/.globuspath). Just runalcf-proxy auth loginonce;alcf-proxy auth statusprints the exact path in use. - Binding to a non-loopback host (
--host 0.0.0.0) is refused unlessALCF_PROXY_API_KEYis set, because the proxy injects your real ALCF token for every caller.
First-time login
Run this once per machine before serve / models:
alcf-proxy auth login
It opens your default browser for Globus OAuth and starts a short-lived local callback server to
receive the result, then stores the refresh + access tokens (good for months) in globus-sdk's
per-platform location. Verify with alcf-proxy auth status.
- Windows / macOS / Linux desktop: works out of the box — the browser opens and the local
callback completes automatically. No
~/.globuspath is assumed; the token location is whatever globus-sdk chooses for your OS (%LOCALAPPDATA%on Windows), shown byauth status. - Headless / remote (SSH, no local browser): the local-callback flow needs a browser that can
reach
localhoston the login machine. If you're on a headless box, runalcf-proxy auth loginon a machine that has a browser using the same OS user profile / token dir, or forward the callback port over SSH. (A copy-paste device-code fallback is not yet implemented.)
Usage
alcf-proxy auth login # one-time Globus browser login
alcf-proxy auth status # authenticated? token path + hours left
alcf-proxy serve # start the gateway (reads config or uses defaults)
alcf-proxy serve --port 8080 --host 0.0.0.0
alcf-proxy serve --cluster metis --framework api --model gpt-oss-120b
alcf-proxy models # list models currently served by ALCF
alcf-proxy models --json # machine-readable
alcf-proxy health # token status / hours remaining
alcf-proxy config init # write a starter config file
alcf-proxy config show # print the effective config
Point your CLI at it
Codex (~/.codex/config.toml or $CODEX_HOME/config.toml):
[model_providers.alcf]
name = "ALCF (via alcf-proxy)"
base_url = "http://localhost:11445/v1"
wire_api = "responses"
# no api key needed — the proxy injects the real ALCF token; set a dummy if the client requires one
Any OpenAI-compatible client (Aider, OpenCode, OpenAI SDK): set the base URL to
http://localhost:11445/v1 and any non-empty API key.
Claude Code: set the Anthropic base URL to http://localhost:11445 and any dummy key.
Models
alcf-proxy forwards to any model ALCF serves. Run alcf-proxy models for the live list. Feature
flags: B = batch, T = tool calling, R = reasoning, H = always hot.
⭐ Recommended: openai/gpt-oss-120b — large reasoning model, always hot, tool calling + batch,
available on both clusters (Sophia openai/gpt-oss-120b, Metis gpt-oss-120b); it's the built-in
default.
Model (Sophia sophia/vllm) |
B | T | R | H |
|---|---|---|---|---|
⭐ openai/gpt-oss-120b |
✅ | ✅ | ✅ | ✅ |
openai/gpt-oss-20b |
✅ | ✅ | ✅ | ✅ |
meta-llama/Llama-4-Scout-17B-16E-Instruct |
✅ | ✅ | ✅ | |
meta-llama/Llama-4-Maverick-17B-128E-Instruct |
✅ | |||
meta-llama/Llama-3.3-70B-Instruct |
✅ | ✅ | ||
meta-llama/Meta-Llama-3.1-{8B,70B,405B}-Instruct |
✅ | ✅ | * | |
google/gemma-3-27b-it |
✅ | ✅ | ✅ | |
google/gemma-4-{31B,E4B}-it |
✅ | ✅ | ✅ | |
nvidia/nemotron-3-super-120b |
✅ | ✅ | ||
arcee-ai/Trinity-Large-Thinking-W4A16 |
✅ | ✅ | ||
mistralai/{Mistral-Large-2407,Devstral-2-123B,Mixtral-8x22B} |
Metis (metis/api, no openai/ prefix, all always-hot; no batch/tools): gpt-oss-120b ⭐,
Llama-4-Maverick-17B-128E-Instruct, Mistral-Large-3-675B-Instruct-2512, gemma-4-31B-it.
Also on Sophia: vision (meta-llama/Llama-3.2-90B-Vision-Instruct), embeddings
(Salesforce/SFR-Embedding-Mistral, genslm-*), and segmentation (facebook/sam3). Full table with
every model: docs → Models.
Configuration
YAML file (search order: ./config.yaml, then the platform user-config dir). CLI flags and
ALCF_PROXY_* env vars override the file. See config.example.yaml for all
options, including the optional explicit endpoints: failover list.
Precedence: CLI flags > env (ALCF_PROXY_*) > config file > built-in defaults.
How it works
client (chat / responses / messages)
│ request
▼
alcf-proxy ──translate(req)──► IR ──► ALCF chat/completions (stream:true) + Bearer(auto)
▲ │ real streamed chat chunks
│ client-format SSE ◄──translate(stream)── IR ◄──
│
└─ EndpointSelector: on 503/maintenance, fail over to the next endpoint (sticky)
The ALCF token lives only in the proxy process memory; it is never written to any client config.
Layout
alcf_proxy/
cli.py # serve / models / health / config
config.py # YAML + env + CLI config; endpoint failover list
alcf_auth.py # internalized Globus auth (cross-platform token storage)
auth.py # TokenManager: in-process fetch + refresh-on-expiry
endpoints.py # ALCF URLs + model listing
upstream.py # chat streaming client + EndpointSelector (failover)
translate.py # llm-rosetta engine: frontend <-> IR <-> chat
sse.py # SSE codec
server.py # FastAPI: 3 translating routes + /v1/models + /health
formats/ # registry (chat/responses/anthropic) + chat sanitizers
Tests
python -m pytest # unit tests (offline); enforces coverage ≥85%
python -m pytest -m live -o addopts="" # live end-to-end tests (need a valid ALCF token + up cluster)
Unit tests use real ALCF response fixtures under tests/fixtures/ (captured once; model output
only, no secrets).
License
MIT — see LICENSE.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file alcf_proxy-0.1.3.tar.gz.
File metadata
- Download URL: alcf_proxy-0.1.3.tar.gz
- Upload date:
- Size: 28.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd1526835471b9733d1bc1e9e6d1f91d6a8afe63e546a0197173f81201926778
|
|
| MD5 |
bf8a1d4aff5db2b418a4663ad2875827
|
|
| BLAKE2b-256 |
ba19108e00e54474002f07a6dd8cccd8ca7c8c367ee2601385ff0e555f6910a0
|
File details
Details for the file alcf_proxy-0.1.3-py3-none-any.whl.
File metadata
- Download URL: alcf_proxy-0.1.3-py3-none-any.whl
- Upload date:
- Size: 19.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7af44db6c5b50d87d99bdc5f72901cf9a31cc1a2cfbe05d7260d749c149ab267
|
|
| MD5 |
b927ec5afbce2f91b92127fd4abd7fac
|
|
| BLAKE2b-256 |
2455e61fc75a6f26dcac0efca860e847b8fa13b5fd860a53328dfe9a88bb03fa
|