Aex Brain
Concepts

Model

Bindings, wire formats, and why the model is pinned.

A model binding is a provider, a model name, and a key:

model: {
  provider: "vercel-ai-gateway",
  name: "openai/gpt-5-mini",
  apiKey: process.env.VERCEL_AI_GATEWAY_API_KEY!,
}

Brain implements OpenAI Responses and Anthropic Messages. Provider definitions and model metadata come from the reviewed models.dev snapshot vendored in the repository. Refresh it with tools/fetch-models-dev.mjs and regenerate contracts with npm run gen. There is no runtime catalogue fetch.

ProviderWire dialectModel namesDefault endpoint
vercel-ai-gatewayOpenAI Responsesnamespaced, openai/gpt-5-minihttps://ai-gateway.vercel.sh/v1
openaiOpenAI Responsesbare, gpt-5-minihttps://api.openai.com/v1
anthropicAnthropic Messagesbare, claude-sonnet-4-5https://api.anthropic.com/v1
deepseekOpenAI Responsesbare, deepseek-flashhttps://api.deepseek.com

Chat Completions-only providers and the openai-responses alias are unsupported. Unknown model IDs still pass admission for an existing provider; the provider validates actual model support. DeepSeek uses its Responses endpoint with the customer's DeepSeek key. A models.dev npm package name alone does not establish which protocols an endpoint supports; the generator maps verified Responses providers explicitly and imports their model metadata from the snapshot.

Authenticated GET /v1/models, or brain.models(provider?), returns the composed deployment catalogue, its snapshot digest, input/output modalities and each adapter's supported media forms. Optional metadata stays unknown when absent. attachment: true alone does not establish PDF support. Catalogue metadata helps select models; it is not a guarantee that a gateway implements every feature. Credentials and internal endpoints are excluded.

Image and PDF inputs

UserInput.media and model Tool-result media share two forms: { type: "image", url } and { type: "file", media_type: "application/pdf", url }. Ordered model messages may contain the same blocks alongside text and Tool calls/results. Anthropic rejects developer messages; supply its instructions through system.

URLs must use HTTPS without embedded username/password and be reachable by the model provider. Brain passes the URL to Responses input_image.image_url / input_file.file_url, or an Anthropic URL image / document source. Brain does not fetch, host, upload, convert or refresh attachments. Inline data, local paths and provider file IDs are unsupported, including in known native input positions. Opaque signed thinking and encrypted continuation state remain unchanged. Responses continuation may include file_id: null or file_data: null beside an HTTPS source; Brain preserves those empty optional fields, including after compaction.

The caller owns file storage, access and lifetime. Keep the same bytes available at the same URL for every later turn that needs them. Expiry can cause a later model call to fail, and cannot retract bytes a provider has already fetched. Brain journals references and preserves them across restart. Request limits bound encoded JSON; providers enforce file size, page and model context limits. Download/format failures become ordinary failed model effects, without automatic retry.

Tool execution still returns arbitrary JSON. The Agentloop explicitly maps selected output into Tool-result media. URL length is not an estimate of image or PDF model tokens.

PDF processing varies by provider. If a diagram's visual content is not recognized, supply it as an image or a PDF containing embedded page images.

Native continuation state

{ type: "native", format, data } retains adapter-owned JSON in content order. Keep these blocks unchanged with the messages and Tool turns they accompany. The formats currently implemented are:

FormatRetained state
anthropic.messages.v1Signed and redacted thinking blocks
openai.responses.v1Reasoning and compaction items, including retained items returned by compaction

An incompatible adapter rejects the state. A format identifies its representation, not universal portability across endpoints, credentials, models, or provider versions. Previously discarded state cannot be recovered from older journals. Native blocks are not ordinary display text.

Responses calls are stateless (store: false) and request encrypted reasoning. Set options.operation to compact to call /responses/compact; that operation accepts context and instructions only, with response_format: null to reset an inherited format. Save the returned message as the selected context before continuing. Brain does not compact automatically.

The September 2026 live probe found that Vercel wraps Responses reasoning with gwenc1, while its compaction route forwards to OpenAI, which rejects that wrapper. After the Tool turn completed, explicitly selecting visible context for compaction succeeded, and the returned compaction state continued successfully. Brain preserves the provider error and never silently strips native state.

Per-call options

After a provider stream terminates, Brain checks its stop reason before parsing Tool parameters. Tool calls from a length-limited, refused, or unknown response fail as model_output_incomplete, even if their JSON happens to parse. Invalid Tool JSON from an otherwise completed response fails as model_output_invalid. Neither becomes an executable Tool call.

The durable model_call_failed Event retains the initiating sequence and a response object with stop_reason and provider-reported usage, including reasoning tokens when supplied. Absent counters remain absent. These known unusable responses are distinct from an interrupted stream with an unknown outcome. Brain does not retry either; the Agentloop owns any new attempt.

An omitted response_format inherits the session format; a value replaces it; explicit null resets it. Other provider options are per request and pass only through the selected adapter:

DialectAllowed option keys
Anthropicthinking, output_config, temperature, top_p, top_k, stop_sequences
Responsesoperation, reasoning, temperature, top_p

The provider validates supported values for its model. Options cannot override credentials, destinations, model binding, or Tool authority. Deployment limits bound encoded input and output.

Custom providers

The catalog is data feeding a normalized provider layer, and a deployment can feed that layer itself. --providers-file (BRAIN_PROVIDERS_FILE) names a JSON file of definitions in the same shape, merged over the catalog -- a definition with a catalog provider's name supersedes it:

{
  "providers": [
    {
      "name": "local-responses",
      "dialect": "openai_responses",
      "base_url": "http://127.0.0.1:8088/v1",
      "models": [{ "id": "local-model", "context_window_tokens": 131072 }]
    }
  ]
}

dialect is openai_responses or anthropic_messages. Endpoints can also be overridden per provider without a file: BRAIN_MODEL_BASE_URL (the gateway), BRAIN_OPENAI_BASE_URL, and BRAIN_ANTHROPIC_BASE_URL. Overrides must implement the selected dialect.

For an upgrade from the Chat/inline-media contract, stop the writer and run the candidate image's brain-check-media-upgrade --data-dir PATH --from-chat, adding --providers-file when used. It checks every retained journal, including ended and suspended sessions, without repairing or rewriting records. Incompatible bindings, inline media, old native Chat state and unreadable history stop the upgrade. Resume the previous runtime and arrange explicit migration; never delete retained sessions to make the check pass. Omit --from-chat for subsequent URL-media contract checks.

Pinned for the session

The binding is fixed when the session is created and cannot change while it is alive. A turn cannot silently land on a different model than the one before it, and a replayed log means what it said when it was written.

Change models by starting a new session.

The system prompt, the tools, and the response format are set at create and are not pinned: the agent loop may replace the prompt, offer a subset of the tools, or send a different response format on any model call. A response format is rejected at create for a provider that cannot carry it.

Keys

Keys are yours. Brain holds the binding for the session's lifetime and uses it to make calls; it never writes the key into the log or into an event.

On this page