Skip to content

Configure Your Model (Bring Your Own Keys)

Licensed commands. Every CortexBuild command except auth and the host-invoked hook requires a valid licence. If you see license required, run cortexbuild auth activate --key <token> (or cortexbuild auth refresh if a lease simply lapsed) and try again. --help always works.

In plain English

CortexBuild is model-agnostic and bring-your-own-keys. It never marks up tokens, never stores your keys, and LLM use is opt-in and off by default. Most of the pipeline runs with no model at all.

Not installed yet?

If you haven't installed the CLI yet, do the install first.


Do you even need a model?

The core CortexBuild workflow is deterministic, offline, and free — no LLM required:

Command What it does Needs a model?
cortexbuild init run . Brownfield onboarding (Passes 1–4) No
cortexbuild render Render rules into your AI tools No
cortexbuild render --check CI drift gate No
cortexbuild eval Offline conformance scoring No
cortexbuild conformance Maturity report No
cortexbuild feedback Deterministic feedback synthesis No
cortexbuild debt-heatmap Technical-debt heatmap No
cortexbuild ledger … Recurrence-ledger management No

A model is only needed for the opt-in LLM steps:

  • cortexbuild init run --with-rule-synthesis (convention inference)
  • cortexbuild synthesize-rules (standalone rule synthesis)
  • The LLM-assisted review agent roles (Critic, Security, etc.) when invoked via the orchestrator

If you only use the deterministic path, stop here — you're done.


Turn on LLM features

LLM features are gated behind an environment variable. Set it before running any LLM-dependent command:

export CORTEXBUILD_LLM=1
$env:CORTEXBUILD_LLM = "1"

Without this variable, LLM code paths are never reached — even if a provider is configured.


Native providers

CortexBuild ships two native provider adapters:

Anthropic (default preference)

pip install --upgrade "cortexbuild-core[anthropic]" \
  --find-links https://dist.cortexbuild.dev/index.html

Provide your API key via the provider's standard environment variable (see How it works for the full interface). Anthropic is the first-preference provider in the default routing table.

Google Gemini

pip install --upgrade "cortexbuild-core[gemini]" \
  --find-links https://dist.cortexbuild.dev/index.html

Provide your API key via the provider's standard environment variable. See How it works for configuration details.

Both adapters support the ModelTier system (reasoning_heavy, balanced, fast_cheap) so CortexBuild can route tasks to the right cost/capability tier automatically.


Any other model via an OpenAI-compatible endpoint

Everything beyond the two native adapters — including local / self-hosted models and cloud gateways — is reached through a single OpenAI-compatible base_url seam.

Install the OpenAI-compatible extra:

pip install --upgrade "cortexbuild-core[llm]" \
  --find-links https://dist.cortexbuild.dev/index.html

Then create .cortexbuild/llm-config.yaml in your repo:

# .cortexbuild/llm-config.yaml
schema_version: 1
provider: ollama
model: llama3
base_url: http://localhost:11434/v1
api_key_env: OLLAMA_API_KEY
locality: local

Key fields:

Field Purpose
schema_version Always 1 (current).
provider A human-readable label (e.g. ollama, vllm, lm-studio, bedrock-proxy).
model The model name your endpoint expects.
base_url The OpenAI-compatible endpoint URL.
api_key_env Name of the environment variable holding the API key. Never put a raw key in this file — inline secrets are rejected at parse time (fail-closed). A keyless local endpoint may omit this field.
locality local (loopback, no bytes leave the machine), self_hosted_lan (operator-controlled LAN host — off-box), or cloud. Recorded as data; the egress redaction choke-point wraps every endpoint regardless.

Local / self-hosted models

Any server that exposes an OpenAI-compatible /v1/chat/completions endpoint works:

Server Typical base_url
Ollama http://localhost:11434/v1
vLLM http://localhost:8000/v1
LM Studio http://localhost:1234/v1
text-generation-inference http://localhost:8080/v1

Set locality: local for on-box servers (zero egress) or locality: self_hosted_lan for a LAN-hosted GPU server.

Model gateways (LiteLLM, OpenRouter) and clouds behind them

CortexBuild ships no native AWS Bedrock, Google Vertex, or Azure OpenAI adapter. It does not need one: those clouds — and every other vendor — are reachable through an OpenAI-compatible gateway. CortexBuild talks to the gateway; the gateway talks to the vendors.

This is also how you get one model per tier from one endpoint and one key:

schema_version: 1
provider: litellm
model: openai/gpt-5-mini          # the fallback when a tier is unset
base_url: http://localhost:4000/v1
api_key_env: LITELLM_API_KEY      # env var NAME — never the value
locality: cloud

tiers:
  reasoning_heavy: anthropic/claude-opus-4-7
  balanced:        openai/gpt-5-mini
  fast_cheap:      groq/llama-3.1-8b-instant

allocation:
  objective: [cost, quality]

All three blocks live in the same file, and a gateway is the only place the credentials for those three vendors appear. Swap base_url for https://openrouter.ai/api/v1 and the model ids for OpenRouter's, and nothing else changes.

A tier you leave out of tiers: resolves to the default client rather than inheriting another tier's model, so a partial block is a valid configuration.

Two things a gateway does not exempt you from:

  • Recorded egress consent. locality: cloud is off-box, and a request is refused with EgressConsentError until a scoped llm-assist-egress consent is recorded in .cortexbuild/egress-consent.json. Pointing at localhost:4000 does not make the bytes local when LiteLLM forwards them to three vendors.
  • Keys by reference only. api_key_env names an environment variable. An inline api_key: is a hard parse error, not a warning — and a gateway makes that key more valuable, not less, since it fronts every vendor at once.

This path is verified end-to-end offline, including that each model tier reaches the gateway with its own distinct model id.


Picking the right model per task (cost optimisation)

CortexBuild's model router (see How it works) defines three model tiers:

Tier Best for Example models
reasoning_heavy Planner, Critic, Security Compliance, PR Reviewer — authoring or gating high-consequence output Claude Opus, GPT-5
balanced Builder, Tester Validator, Optimizer — most volume, cost matters Claude Sonnet, GPT-5-mini
fast_cheap Explore — read-only summarisation Claude Haiku, GPT-5-nano

The Critic's default tier is reasoning_heavy, same as the Planner it reviews — but it never actually runs on the same model as the Planner. Routing automatically resolves the Critic one tier down from whatever the Planner resolves to (so reasoning_heavy becomes balanced by default), because reviewing on the same model as the author would lose the independence rule-critic-gate requires. The routing preview below always shows this resolved tier, not the raw table entry above.

See the routing before you pay for it

cortexbuild orchestrate tiers --title "add payment_status column" --schema-change

No LLM call, no spend. It prints the tier each agent would run on and why:

planner   reasoning_heavy  changes the schema; planner authors or gates that work
critic    balanced         changes the schema; critic authors or gates that work

Add --objective cost,quality to try an objective without editing config — comparing objectives is the main reason to reach for this command.

orchestrate run and orchestrate batch route on this same plan and report it: run --json as tier_plan, batch --json as tier_plans — a list aligned with outcomes, one entry per backlog row (a backlog mixes a typo fix with a migration, so one figure for the batch answers nothing). "Why did that task cost that much" is answerable from the run record.

Steer it with an allocation objective

# .cortexbuild/llm-config.yaml
allocation:
  objective: [cost, quality]   # or [speed, ...] or [quality, ...]

cost or speed first moves every agent one tier down; quality first moves one tier up. One step, deliberately — collapsing every agent onto the cheapest model would destroy the reviewer-differs-from-author guarantee.

The objective is applied to each role's raw capability tier and the Critic's independence offset is re-applied afterwards, so no objective can absorb it. (The other order is subtly wrong: a step saturates at the ceiling, so quality would leave the Planner at reasoning_heavy while raising the Critic onto it.)

Two limits worth knowing

Risk sets a floor an objective cannot cross. On a task that touches auth/RBAC/PII, changes the schema, adds a public API or a deployment target, spans more than one system, or is marked medium/high risk, no agent drops to fast_cheap — whatever the objective says. An objective is a preference; risk is a constraint.

That floor can cost you cross-model review. On a risky task under a cost or speed objective, the Planner steps down to balanced and the Critic is held up at balanced by the floor — so both land on one model. This is the only combination that collapses them. CortexBuild says so rather than silently accepting it:

⚠ Critic and Planner resolved to the SAME tier — cross-model review is lost
  for this task (rule-critic-gate).

It warns; it does not block. Drop the objective for that task, or accept that the plan is reviewed by its own model.

The Planner proposes subtasks and models; governance disposes

CortexBuild has no model of its own — it is a governance platform. The judgement about what the subtasks are and which model each deserves comes from your LLM: the Planner agent, which is already a gated, paid-for turn. CortexBuild supplies the rails and checks the result.

  • Own-orchestrator mode — the Planner's verdict may include subtasks, each with a suggested_tier and the risk signals that justify it. Governance validates every suggestion: a risky subtask suggested fast_cheap is raised to the floor with the reason recorded, a missing or invalid suggestion degrades to the cheapest tier governance allows, and a malformed entry is dropped and counted — a partial plan says it is partial. The governed plan lands in orchestrate run --json as subtask_plan, with the LLM's original ask (llm_suggested_tier) kept on record next to the governed answer.
  • Rendered-host mode — the Planner persona instructs your host's model to produce a ## Subtasks & Model Plan table in plan.md under the same rules, and to cross-check against cortexbuild orchestrate tiers (offline, no spend).

No new model call is added in either mode: the decomposition rides inside the Planner turn you were already paying for. A Planner that emits no subtasks (an older model, a dry run) changes nothing — the deterministic tier plan above remains the routing answer. Proposals refine it; they never replace the floor.

  1. Use cheaper / local models for narrow, low-risk, deterministic-adjacent steps (exploration, documentation drafts).
  2. Use stronger cloud models for Planner, Security Compliance, and PR Reviewer — the roles that author or gate high-consequence output. The Critic is deliberately not on this list: it sits one tier below the Planner it reviews, because independence beats raw capability for a reviewer.
  3. Validate outputs with the deterministic gates (eval, conformance, render --check) — these are free and catch regressions regardless of which model produced the change.
  4. Fall back to a stronger model when a cheaper model's output fails validation.

You can override the default tier routing per project and per agent. See How it works — the governed workflow roles for the routing table.

This applies to own-orchestrator mode

Tier routing governs CORTEXBUILD_LLM=1 runs, where CortexBuild picks the model. In rendered-into-host mode the host tool picks; CortexBuild writes the tier into each agent file as a model: request the host may honour or ignore. See Install — Per-agent model tiers.


Privacy & egress

Your keys are yours, by-reference only (environment variables), and are never persisted or logged by CortexBuild. The system is offline by default — nothing leaves your machine unless you explicitly opt into an LLM call or an explicit egress action. Every LLM endpoint (including local ones) is wrapped by the egress redaction choke-point, which scrubs sensitive tokens before any request is sent.


Next