Skip to main content

ALCF-proxy

PyPI version Python versions License: MIT Coverage Docs

📖 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/completions upstream 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.
  • Unified model routing (v0.2.0): one pool across all ALCF clusters (Sophia, Metis, Minerva). Request any model id — the proxy resolves which cluster serves it (remapping per-cluster ids like openai/gpt-oss-120b vs gpt-oss-120b), sticks to a working cluster, and fails over automatically on 503/maintenance. No per-cluster configuration, ever.

Prerequisites

  • Python ≥ 3.10. All auth is built in (via globus-sdk, installed automatically); you do not need ALCF's inference_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 with alcf-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-sdk in its standard per-platform app-data dir (on Windows this is under %LOCALAPPDATA%, resolved automatically — no hard-coded ~/.globus path). Just run alcf-proxy auth login once; alcf-proxy auth status prints the exact path in use.
  • Binding to a non-loopback host (--host 0.0.0.0) is refused unless ALCF_PROXY_API_KEY is 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 ~/.globus path is assumed; the token location is whatever globus-sdk chooses for your OS (%LOCALAPPDATA% on Windows), shown by auth status.
  • Headless / remote (SSH, no local browser): the local-callback flow needs a browser that can reach localhost on the login machine. If you're on a headless box, run alcf-proxy auth login on 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.)

Upgrading from v0.1.x

pip install -U alcf-proxy and restart the proxy — client configs and config.yaml keep working as-is. Three behavior changes to know (unknown models now 400 instead of silent remap; /v1/models is now OpenAI-shaped; ALCF_PROXY_API_KEY is now enforced): see docs → Upgrading.

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 Sophia (openai/gpt-oss-120b) and Metis (gpt-oss-120b); it is 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 ⭐, Mistral-Large-3-675B-Instruct-2512, gemma-4-31B-it. Minerva (minerva/api, NVIDIA B200, new): nemotron-3-ultra (always hot).

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.

Citation

If you use this software in your research, please consider citing:

@misc{alcf_proxy,
  title = {ALCF-proxy: Translating gateway for ALCF inference endpoints},
  author = {Jin, Hongwei},
  year = {2026},
  url = {https://github.com/cshjin/alcf-proxy},
}

Metadata

Release files for alcf-proxy 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for alcf-proxy 0.2.0
File Size Uploaded
alcf_proxy-0.2.0.tar.gz 35.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for alcf-proxy 0.2.0
File Interpreter ABI Platform
alcf_proxy-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 59.6 kB

Release files / alcf_proxy-0.2.0.tar.gz

Download URL alcf_proxy-0.2.0.tar.gz
Size 35.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0937c0c87e181b673f3b740d3cb544accc37bdf042325fdca9be39dba6f739d9
BLAKE2b-256 checksum
How to use checksums
23875835af4255189831d31018d88efb8ffc6a483223f0882a02a31f92bbba74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / alcf_proxy-0.2.0-py3-none-any.whl

Download URL alcf_proxy-0.2.0-py3-none-any.whl
Size 24.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4d47fa949e9dbe8ac0bcdc3b9a790ac560040f371995e74d67d3cd56bf7c8c79
BLAKE2b-256 checksum
How to use checksums
1994dae0643a25668e2c45564e8f2964df06f7a8e8fc166568fdeac448396bc9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page