LLM providers
pibox configures Pi’s upstream model through environment variables. This is separate from pibox’s OpenAI-compatible endpoint at /openai/v1.
Pi supports these custom HTTP APIs:
PIBOX_PROVIDER_API | Endpoint type |
|---|---|
openai-completions | OpenAI Chat Completions compatible endpoints, including LiteLLM |
openai-responses | OpenAI Responses compatible endpoints |
anthropic-messages | Anthropic Messages compatible endpoints, including Z.AI |
google-generative-ai | Google Generative AI compatible endpoints |
Set the provider URL, protocol, token, and default model when starting the container:
| Variable | Default | Purpose |
|---|---|---|
PIBOX_PROVIDER_NAME | pibox | Pi provider identifier. Lowercase letters, numbers, and -, starting with a letter, at most 64 characters. |
PIBOX_PROVIDER_API | openai-completions | One API from the table above. |
PIBOX_PROVIDER_BASE_URL | required | Upstream HTTP base URL. |
PIBOX_PROVIDER_API_KEY | required | Upstream API key or token. |
PIBOX_PROVIDER_MODEL | required | Default upstream model ID. |
Setting any one of them turns on the generic provider, and then the URL, key and model are all required. With the wrapper, set them on the host as in the quick start. The examples below use plain docker run.
LiteLLM uses its OpenAI-compatible /v1 URL:
docker run --rm --network host \
-e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \
-e PIBOX_PROVIDER_API=openai-completions \
-e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \
-e PIBOX_PROVIDER_MODEL=your-model-id \
-v "$PWD/workspace:/workspace" \
psyb0t/pibox:latest \
-p "list the files in /workspace"
An Anthropic-compatible endpoint, including a Z.AI endpoint, uses the same variables with another protocol and base URL:
docker run --rm \
-e PIBOX_PROVIDER_BASE_URL=https://api.z.ai/api/anthropic \
-e PIBOX_PROVIDER_API=anthropic-messages \
-e PIBOX_PROVIDER_API_KEY=your-z-ai-api-key \
-e PIBOX_PROVIDER_MODEL=your-model-id \
-v "$PWD/workspace:/workspace" \
psyb0t/pibox:latest \
-p "list the files in /workspace"
Z.AI Coding Plan also exposes an OpenAI-compatible coding endpoint. Use a Coding Plan model that the account can call. The endpoint lists models at GET /models. The Anthropic endpoint lists models at GET /v1/models.
docker run --rm \
-e PIBOX_PROVIDER_BASE_URL=https://api.z.ai/api/coding/paas/v4 \
-e PIBOX_PROVIDER_API=openai-completions \
-e PIBOX_PROVIDER_API_KEY=your-z-ai-api-key \
-e PIBOX_PROVIDER_MODEL=glm-5.3-flash \
-v "$PWD/workspace:/workspace" \
psyb0t/pibox:latest \
-p "list the files in /workspace"
For API mode, list the upstream models in PIBOX_AVAILABLE_MODELS so pibox can advertise and validate them. pibox registers every listed model with the provider under PIBOX_PROVIDER_API, so callers can request any of them, not only PIBOX_PROVIDER_MODEL. A model that Pi has no registration for falls back to Pi’s default API shape, which disagrees with an Anthropic Messages base URL and fails with Stream ended without finish_reason:
docker run -d --name pibox --network host \
-e PIBOX_API_MODE=1 \
-e PIBOX_AVAILABLE_MODELS=your-model-id \
-e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \
-e PIBOX_PROVIDER_API=openai-completions \
-e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \
-e PIBOX_PROVIDER_MODEL=your-model-id \
-v "$PWD/workspace:/workspace" \
psyb0t/pibox:latest
What startup writes
At every container start, setup-provider-env.sh writes Pi’s provider entry to /home/aicode/.pi/agent/models.json and records the selected provider and model in /home/aicode/.pi/agent/pibox-provider.json. Other providers in models.json are kept. The entrypoint passes PIBOX_PROVIDER_API_KEY to the unprivileged Pi process as OPENAI_API_KEY, and models.json stores the $OPENAI_API_KEY reference, not the key value. Restart the container after changing configuration.
Every model is registered with a 128,000-token context window and a 16,384-token output limit. The script logs to stderr and to /tmp/pibox-provider-setup.log inside the container. Invalid settings stop the container before any mode starts. Troubleshooting lists the messages.
When the base URL contains /anthropic but PIBOX_PROVIDER_API is not anthropic-messages, or the reverse with a /v<number> path, startup logs a provider_api_base_url_mismatch warning and continues. A mismatched protocol otherwise shows up later as a truncated stream.
Anthropic compatibility
Existing ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, and ANTHROPIC_MODEL deployments keep working. They are a compatibility shortcut for Anthropic Messages endpoints. Do not set PIBOX_PROVIDER_* with ANTHROPIC_BASE_URL. pibox exits instead of selecting an ambiguous provider.
| Variable | Purpose |
|---|---|
ANTHROPIC_AUTH_TOKEN | Bearer token for Z.AI, Anthropic or another Anthropic Messages endpoint |
ANTHROPIC_API_KEY | Used when ANTHROPIC_AUTH_TOKEN is empty |
ANTHROPIC_BASE_URL | Endpoint. Setting it turns on the managed anthropic provider entry |
ANTHROPIC_MODEL | Default model when the caller does not name one |
The wrapper forwards only PIBOX_* names, so send these through it with the PIBOX_ENV_ prefix:
PIBOX_ENV_ANTHROPIC_AUTH_TOKEN=your-z-ai-api-key \
PIBOX_ENV_ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \
PIBOX_ENV_ANTHROPIC_MODEL=your-model-id \
pibox -p "explain this project"
With ANTHROPIC_BASE_URL set, startup writes an anthropic provider into models.json with the token itself as the key, not an environment reference, and registers ANTHROPIC_MODEL plus every model in PIBOX_AVAILABLE_MODELS. See Security.
Pi also reads its usual provider keys, such as OPENAI_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY and ZAI_API_KEY, for its built-in providers. The base entrypoint passes those through to Pi unchanged. Through the wrapper they also need the PIBOX_ENV_ prefix.
The generic provider variables cover Pi’s documented custom HTTP APIs. They do not configure every cloud-specific Pi provider through a base URL.