9.5 KiB
Local Pi model configuration
Pi orchestrates the NL-to-SQL workflow and resolves built-in models and OpenAI-compatible providers
declared in the local catalog. ThothII applies a stricter rule than Pi: code in
harness/.pi/extensions/ cannot register a provider or custom model. Endpoints, protocols,
compatibility settings, and model identifiers belong exclusively in the local files
deploy/pi/models.json and deploy/pi/settings.json.
ThothII operator note: ThothII runs Pi only in Docker Compose. Paths under
~/.pi/agent/in this document describe Pi's container-side behavior. Operators editdeploy/pi/models.jsonanddeploy/pi/settings.jsonin the ThothII project root and use the protected host credential file selected byPI_AUTH_FILE; they do not edit files inside the running container.
Credentials in the backend container
In production, configure one generic source: the THT_SECRETS_FILE bundle with the
THT_MODEL_API_KEY entry, which is the default for the unified distribution, or
THT_MODEL_API_KEY_FILE as an absolute secret-file path. Do not put the key value in .env.
For each process, PiProcessManager rereads and validates the source, normalizes the selected
provider, and passes only the appropriate native variable to the Pi child
(ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, ZAI_API_KEY, and so on). It removes the
generic path, keys for unselected providers, and the old PI_PROVIDER_API_KEY from the child
environment. For a custom provider, the backend derives the variable name from the declarative
apiKey field in models.json; a literal value means the catalog is self-contained. Provider-name
exceptions are not compiled into the code. A missing or insecure secret fails before spawn with a
sanitized error.
The generic source supports only single-key providers: ant-ling, anthropic,
cerebras, deepseek, fireworks, github-copilot, google (including the gemini alias),
google-vertex in API-key mode, groq, huggingface, kimi-coding, minimax, minimax-cn,
mistral, moonshotai, moonshotai-cn, nvidia, openai, opencode, opencode-go,
openrouter, together, vercel-ai-gateway, xai, the four xiaomi* providers, zai, and
zai-coding-cn.
The composite providers amazon-bedrock, azure-openai-responses, cloudflare-workers-ai, and
cloudflare-ai-gateway cannot be represented by one file. Selection fails before spawn, including
when models are listed. AWS, Azure, and Cloudflare environment credentials are still removed. A
future provider-specific configuration will be needed to support these bundles unambiguously.
Model sources
1. Built-in (compiled into Pi)
Pi ships with a list of known models (models.generated.js in the @earendil-works/pi-ai package):
Anthropic, OpenAI, Google, and third-party providers with well-known public APIs such as DeepSeek.
These require no configuration beyond credentials, provided through an environment variable or
pi auth.
deepseek/deepseek-v4-pro is one of these models. It is included in Pi because api.deepseek.com
is a documented public API, not an internal endpoint.
2. User-level models.json (~/.pi/agent/models.json)
For an OpenAI-compatible endpoint that is not built in but needs no special transport logic,
declare it with its baseUrl, apiKey, and model list. This file exists only at user level; there is
no project-level equivalent, and ./.pi/models.json is not read.
In ThothII-managed installations, the file must be entirely declarative. ThothII recursively
rejects any JSON value that starts with !, including values inside headers, models,
modelOverrides, compat, arrays, or fields it does not yet know. Pi 0.80.3 would treat that
prefix as a shell command when making a request, so managed model catalogs do not allow it. The
returned error is fixed and contains no command, path, or secret.
For secrets, use an environment reference such as "$ZAI_API_KEY" or "${ZAI_API_KEY}". The
backend can populate the native variable for the selected provider by reading
THT_MODEL_API_KEY_FILE, or from the THT_SECRETS_FILE bundle (THT_MODEL_API_KEY). Credentials
can also come from the protected file mounted through PI_AUTH_FILE, with apiKey omitted from
models.json. There is no direct secret-file reference syntax in models.json. With THT_MODEL_*
sources, ThothII reads the file and turns it into the Pi child's environment variable; PI_AUTH_FILE
is mounted instead as a protected Pi credential store. For a literal leading exclamation mark, Pi's
declarative syntax is $!, not !.
Real example in use on this machine: GLM (provider zai):
{
"providers": {
"zai": {
"baseUrl": "https://api.z.ai/api/coding/paas/v4",
"api": "openai-completions",
"apiKey": "$ZAI_API_KEY",
"models": [
{
"id": "glm-5.2",
"name": "GLM-5.2",
"reasoning": true,
"contextWindow": 200000,
"maxTokens": 131072
}
]
}
}
}
Because it is user-level, GLM is visible to every project.
Extension providers: not allowed in ThothII
Pi technically supports providers registered by JavaScript extensions, but ThothII does not use
that capability. Project extensions are reserved for the workflow and gates; they must not contain
registerProvider(...). An endpoint that cannot be described by the OpenAI-compatible catalog is
not supported by this installation until the declarative contract is extended generically.
Summary table (current machine state)
| Model | Level | Why | Visibility |
|---|---|---|---|
deepseek/deepseek-v4-pro |
Built-in Pi | Known public API, already in the build | All projects |
zai/glm-5.3 |
deploy/pi/models.json |
Custom OpenAI-compatible endpoint | ThothII installation |
local-qwen/qwen3.6-35b-a3b |
deploy/pi/models.json |
Locally configured OpenAI-compatible endpoint | ThothII installation |
Choosing the right level for a new model
- Is the endpoint a public API already known to Pi? Enable the exact identifier in
deploy/pi/settings.json. - Is it OpenAI-compatible but not built in? Declare it in
deploy/pi/models.json, then enable it indeploy/pi/settings.json. - Does it require provider-specific transport code? Do not add a provider-specific extension. The provider is unsupported until a generic declarative capability exists.
User versus project scope: general summary
In addition to models, Pi loads other resources from two parallel trees: ~/.pi/agent/ (user) and
<cwd>/.pi/ (project, resolved from the directory where pi is launched).
| File/Directory | Livello utente | Livello progetto | Auto-discovery | Precedenza |
|---|---|---|---|---|
models.json |
~/.pi/agent/models.json |
not supported | no | user only |
settings.json |
~/.pi/agent/settings.json |
./.pi/settings.json |
no | project overrides user |
extensions/ |
~/.pi/agent/extensions/ |
./.pi/extensions/ |
yes (.ts/.js) |
merged (project + user) |
prompts/ |
~/.pi/agent/prompts/ |
./.pi/prompts/ |
yes (.md) |
merged |
themes/ |
~/.pi/agent/themes/ |
./.pi/themes/ |
yes (.json) |
project preferred |
skills/ |
~/.pi/agent/skills/ |
./.pi/skills/ |
yes (.md) |
merged |
Real example: ThothII
harness/.pi/
├── extensions/
│ ├── tht-gate.js # human-in-the-loop gate
│ └── gate/
│ ├── core/ # shared gate enforcement and utilities
│ ├── disambiguation/ # F1/F3 policy
│ └── memory/ # F2/F8 policy
├── settings.json # optional override of user settings
└── themes/
└── thothii-mono.json # project theme
Behavior relative to cwd
The directory from which you launch pi determines which workflow extensions are found, but not
which models ThothII makes available. The catalog is mounted in the container's Pi agent directory.
# From harness/: load the project gate and mounted local catalog
cd /path/to/ThothII/harness
pi --model local-qwen/qwen3.6-35b-a3b "..."
The ThothII backend always launches Pi with cwd: harnessDir for the workflow. Model availability
continues to depend only on models.json, settings.json, and local credentials.
Auto-discovery trap: .mjs is ignored
Pi's extension auto-discovery pattern is /\.(ts|js)$/; it does not include .mjs.
.pi/extensions/
├── my-extension.js ✅ auto-loaded
├── my-extension.ts ✅ auto-loaded
├── my-extension.mjs ❌ silently ignored (does not match the pattern)
└── shared-module.mjs ✅ suitable for helper modules (deliberately not loaded as an extension)
If an extension imports a shared module, use .mjs so Pi does not treat it as an extension on its own.
Verifica
List models
pi --list-models
This shows built-in models and models declared in models.json.
Check the catalog used by the application
cd harness # or the project's relevant cwd
pi --mode rpc
# poi: {"type": "get_available_models", "id": "1"}
The RPC response must include only built-in models or models declared in the local catalog.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Model "X/Y" not found |
Provider/model missing from models.json or identifier missing from enabledModels |
Fix the two local files and reload Pi |
| Project settings not applied | Project settings.json has a syntax error, or pi is launched from the wrong cwd |
Validate the JSON and check the cwd |