◉ Overview
Pi is a powerful coding agent — but it only has a TUI. What if you want to talk to it from a web chat interface like Open WebUI, ChatBox, or TypingMind? Or use it as a drop-in replacement for OpenAI's GPT API?
Pi OpenAI Bridge is a Pi extension that starts an HTTP server implementing the OpenAI Chat Completions API. Any application that can talk to OpenAI can now talk to your Pi agent — complete with your skills, extensions, context files, and custom brain.
1 What It Does
The extension adds an OpenAI-compatible HTTP API to your running Pi instance:
POST /v1/chat/completions— the standard OpenAI chat endpoint, with streaming supportGET /v1/models— lists the Pi agent as an available "model"GET /health— health check for monitoring/bridge— a Pi slash command to check the bridge status
This means you can point any OpenAI-compatible client at http://localhost:11434 and chat with your fully-configured Pi agent — with all its skills, AGENTS.md brain, extensions, and tools active.
2 Architecture
Open WebUI / ChatBox
:11434/v1/chat
pi -p "prompt"
GPT / Claude / etc
The bridge receives OpenAI-formatted requests, converts them into Pi print-mode invocations (pi -p), captures the output, and returns it in OpenAI response format. For streaming, it sends Server-Sent Events (SSE) as Pi generates output.
3 Installation
Step 1: Download the extension
Or manually copy the pi-openai-bridge.ts file to:
Step 2: Reload Pi
If Pi is already running, use:
Or restart Pi. You should see:
Step 3: Verify
Expected response:
/bridge inside Pi to check the bridge status and see a quick reference of all endpoints.4 Configuration
Configuration is done via environment variables. Set these before starting Pi:
| Variable | Default | Description |
|---|---|---|
PI_BRIDGE_PORT | 11434 | HTTP port for the bridge server |
PI_BRIDGE_HOST | 127.0.0.1 | Bind address. Use 0.0.0.0 to listen on all interfaces (for remote access) |
Example: custom port
Example: allow remote connections
PI_BRIDGE_HOST=0.0.0.0 exposes your Pi agent to the network. The bridge has no authentication — anyone who can reach the port can use your agent (and spend your LLM tokens). Use a reverse proxy with auth or Tailscale for remote access.5 API Reference
POST /v1/chat/completions
The main endpoint. Accepts the standard OpenAI Chat Completions request format:
GET /v1/models
Returns a list with a single model (pi-agent). Required by most chat UIs during setup.
GET /health
Simple health check. Returns {"status": "ok"}.
Response format
Standard OpenAI Chat Completion response:
6 Testing with curl
Basic request
With system prompt
Streaming
7 Connect a Chat UI
Open WebUI
- Go to Settings → Connections
- Add a new OpenAI-compatible connection
- Set the URL to
http://localhost:11434/v1 - API key: any string (e.g.,
not-needed) — the bridge doesn't check it - The model
pi-agentshould appear in the model list
ChatBox
- Open Settings → AI Provider
- Select "OpenAI API Compatible"
- API Host:
http://localhost:11434 - API Key: any string
- Model:
pi-agent
TypingMind
- Go to Custom Model
- API Endpoint:
http://localhost:11434/v1/chat/completions - Model ID:
pi-agent
Python (openai SDK)
8 Streaming
When "stream": true is set in the request, the bridge returns Server-Sent Events (SSE) following the OpenAI streaming protocol:
- Initial chunk with
role: "assistant" - Content chunks as Pi generates output — each containing a fragment of the response
- Final chunk with
finish_reason: "stop" - Terminator:
data: [DONE]
Most chat UIs use streaming by default for a responsive typing effect. The bridge handles this transparently — you don't need to configure anything special.
9 How It Works Under the Hood
The bridge uses Pi's print mode (pi -p "prompt") to process each request:
- Request arrives — the bridge parses the OpenAI-formatted JSON body
- System prompt extraction — messages with
role: "system"are concatenated and passed via--append-system-prompt - Conversation assembly — multi-turn conversations are formatted into a structured prompt. Single-turn messages are passed directly.
- Pi invocation — the bridge spawns
pi -p "prompt"as a subprocess. Pi loads all your AGENTS.md, brain, skills, and extensions normally. - Response formatting — Pi's output is wrapped in the OpenAI response JSON format with usage estimates
pi -p (print mode) means every request goes through the full Pi pipeline — your AGENTS.md, brain.md, skills, and context files all apply. The API response IS your Pi agent, not a raw model.10 Limitations & Considerations
| Feature | Status | Notes |
|---|---|---|
| Chat completions | ✅ Full | Streaming + non-streaming |
| System prompts | ✅ Full | Passed via --append-system-prompt |
| Multi-turn conversations | ⚠️ Partial | History formatted as structured prompt, not true session continuity |
| Tool use / function calling | ❌ Not yet | Pi tools (read/write/edit/bash) are available but tool-call API format is not mapped |
| Image/vision inputs | ❌ Not yet | Would require mapping multimodal message format |
| Authentication | ❌ None | Add via reverse proxy (nginx/Caddy) or Tailscale |
| Embeddings | ❌ N/A | Pi doesn't provide embedding models |
| Token counting | ⚠️ Estimated | Usage counts are approximated (chars/4), not real token counts |
pi -p process. Conversation history from the chat UI is included in the prompt, but Pi doesn't maintain a persistent session across API calls. This means Pi's session features (tree navigation, fork, compact) are not available through the API.11 Troubleshooting
Bridge doesn't start
- Check that the file is at
~/.pi/agent/extensions/pi-openai-bridge.ts - Run
/reloadin Pi - Check Pi's console output for errors
Port already in use
"pi" command not found in subprocess
- Make sure Pi is installed globally:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent - Or that the
pibinary is in your PATH
Slow responses
Each request spawns a new pi -p process, which includes loading AGENTS.md, brain, and skills. If your agent has many skills or a large brain, there will be startup overhead. Consider:
- Using a fast model (e.g., GPT 5.5 low reasoning)
- Keeping your AGENTS.md lean
- Using streaming mode for a better UX
CORS errors from a web UI
The bridge includes CORS headers by default (Access-Control-Allow-Origin: *). If you're still getting CORS errors, check that your reverse proxy isn't stripping them.