Models & providers
Select models, configure provider API keys, set reasoning effort, route through custom endpoints, and preserve prompt caches.
Brain delegates model inference to the harness runner while keeping provider credentials and transport configuration under host control. When you create a session, you set its model and optional reasoning effort in config.
Model ID format and validation
Pass config.model in provider/model format (1–256 characters) when calling POST /sessions:
{
"harness": "pi",
"config": {
"model": "openai/gpt-4.1-mini",
"reasoning_effort": "low",
"tools": []
}
}Model validation happens in two steps:
- Session creation (
POST /sessions): Brain splitsconfig.modelon the first/, verifies that theproviderprefix exists in your host config'sprovidersmap, and checks that the configuredapi_key_envenvironment variable is non-empty. Missing slashes, unknown providers, or missing credentials fail immediately with400 invalid_request. - Turn execution (Pi runner startup): When the first
user.messagestarts the Pi runner, the runner looks upproviderandmodelin its pinned offline Model catalog (allowModelNetwork: false,refreshOnCreate: false). If the model ID is not in the catalog or the harness falls back to a different model, the turn fails with asession.error(brain_error) event.
Explicit credentials only
Brain authenticates providers with API keys. It passes the resolved key to the runner over stdio in an in-memory credential store (InMemoryCredentialStore) and strips ambient host environment variables when spawning child processes.
Configure providers
Declare each provider prefix in the providers map of your host configuration file (brain.json):
{
"providers": {
"openai": { "api_key_env": "OPENAI_API_KEY" },
"anthropic": { "api_key_env": "ANTHROPIC_API_KEY" }
}
}Every provider entry requires api_key_env, and that environment variable must be set and non-empty when brain starts (or when running brain -check). If a provider's API key changes in the host environment while Brain is running, Brain recycles any idle runner using the old credential before the next turn.
Reasoning effort
Set config.reasoning_effort when creating a session to control extended thinking or reasoning tokens:
| Value | Description |
|---|---|
"off" | Default when reasoning_effort is omitted or "". Disables extended reasoning. |
"minimal", "low", "medium", "high", "xhigh", "max" | Requests the corresponding thinking level from the Pi harness. |
- Any value outside this set is rejected at session creation with
400 invalid_request. - When the Pi runner opens the session, it checks
session.thinkingLevel === options.config.reasoning_effort. If the selected model does not support the requested reasoning effort, the runner fails the turn explicitly withsession.error("requested reasoning effort is unsupported by the model") rather than silently downgrading it.
Custom endpoints and proxies
Each entry in providers accepts optional base_url and api fields to route a catalog provider through an HTTP(S) proxy or OpenAI-compatible gateway:
{
"providers": {
"openai": {
"api_key_env": "OPENAI_API_KEY",
"base_url": "https://my-proxy.example.com/v1",
"api": "openai-completions"
}
}
}base_url: Must be a validhttporhttpsURL with a host and no embedded user credentials.api: Overrides the transport protocol used by the Pi runtime for that provider (for example,"openai-completions"or"openai-responses").- Catalog scope:
base_urlandapioverride transport settings for models that already exist under that provider in the Model catalog; they do not register arbitrary new model IDs.
Prompt caching
Brain and the Pi runner are structured to keep provider prompt prefixes stable across turns, evictions, and checkpoint restores:
- Stable prompt prefixes: The system prompt (
config.instructions) and tool definitions (config.tools) stay constant while a turn runs so provider prompt prefixes remain cacheable across model calls. - Clean system prompts: The Pi runner overrides
before_agent_startso Pi uses your exactconfig.instructions(defaulting to"You are a helpful assistant. Use the available tools when needed.") without appending the runner's private local working directory path, which would invalidate prompt caches when a session moves to another server. - Native state restoration: Reloading an evicted session or restoring an external checkpoint opens Pi's native
.jsonlsession file (SessionManager.open) instead of rebuilding prompts from flattened event text. - No background cache warming: Upstream background cache-warming timers are disabled (
cacheWarming: "off") so idle sessions never make background LLM calls or incur unexpected token charges.