Pi Proxy Server
A gateway that reads your Pi config and exposes every provider as a unified OpenAI + Anthropic API. Configure once in ~/.pi/agent/models.json, use everywhere.
How it works
Three layers. Your providers stay in Pi, the proxy routes to them.
1. Pi config
~/.pi/agent/models.json
You list your real providers here — any baseUrl, any apiKey, any wire format. Pi stores them, the proxy reads them.
~/.pi/agent/models.json
2. Pi Proxy
/api/v1/* endpoints
Reads the config, routes each request to the matching provider by model name. Converts between OpenAI and Anthropic wire formats on the fly.
localhost:3000
3. Your providers
OpenAI · Anthropic · AgentRouter · …
Any provider you configured in Pi. The proxy uses each provider's own baseUrl + apiKey — no central hardcoded upstream.
none configured
Demo mode — available as fallback
If a real upstream is unreachable (WAF, network, etc.), turn on Demo mode in the tester below to verify the proxy plumbing with simulated SSE streams.
Endpoints
Point any OpenAI or Anthropic SDK at these paths.
POST
OpenAI/api/v1/chat/completionsPOST
Anthropic/api/v1/messagesGET
OpenAI/api/v1/modelsGET
—/api/healthGET
—/api/configQuick start
The proxy uses API keys from your Pi config — no separate auth needed.
Point any OpenAI client at base_url="/api/v1". The proxy routes by model name to whatever provider you configured.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:3000/api/v1",
api_key="any-string", # proxy uses keys from your Pi config
)
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Say hi in 5 words."}],
)
print(resp.choices[0].message.content)python
Live tester
Send a real request.
Request
POST /api/v1/chat/completions
Response
Idle
Rendered output · streaming updates in real time
No response yet — hit Send.Raw SSE stream
SSE chunks will appear here…