Skip to content
brain.GitHub
Developer docs OPEN SOURCE
Runtime reference

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:

  1. Session creation (POST /sessions): Brain splits config.model on the first /, verifies that the provider prefix exists in your host config's providers map, and checks that the configured api_key_env environment variable is non-empty. Missing slashes, unknown providers, or missing credentials fail immediately with 400 invalid_request.
  2. Turn execution (Pi runner startup): When the first user.message starts the Pi runner, the runner looks up provider and model in 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 a session.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:

ValueDescription
"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 with session.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 valid http or https URL 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_url and api override 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_start so Pi uses your exact config.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 .jsonl session 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.

On this page