Skip to main content
Codex is an open-source AI coding agent that runs in the terminal. It can read, modify, and execute code across local repositories, helping developers automate development workflows, debug issues, implement features, and interact with codebases through natural language commands.

Build sub-agents with Codex and SambaNova

This is a guide to wiring the OpenAI Codex CLI to a SambaNova-hosted model via the Responses API, and trying it on three real demos — including one that uses an MCP server for live library docs.

What it does

Codex CLI is built around two ideas worth abusing: [model_providers.*] lets you point it at any OpenAI-compatible endpoint, and --profile lets you swap the active model+provider with one flag. Together they make the planner / executor pattern from the SambaNova blog feel native: one profile for the frontier planner (gpt-5, o3, etc), another for MiniMax-M2.7 as the cheap, fast executor. SambaNova exposes a /v1/responses endpoint that matches Codex’s wire_api = "responses" exactly — no LiteLLM proxy required.

Prerequisites

  • Node.js ≥ 18 on PATH.
  • Codex CLI installed: npm i -g @openai/codex (or brew install --cask codex).
  • SambaNova API key exported as SAMBANOVA_API_KEY.
  • (For Demo 2 & 3) an OpenAI API key registered with Codex for the frontier planner profile — see below.
Sanity check:
codex --version && [ -n "$SAMBANOVA_API_KEY" ] && echo "SambaNova OK"

Register your OpenAI key for the frontier planner (Demo 2 & 3)

The plan profile uses Codex’s built-in openai provider, which authenticates from ~/.codex/auth.json. Let Codex write that file for you — export your key and pipe it into codex login:
export OPENAI_API_KEY="sk-…your-key-here…"
printenv OPENAI_API_KEY | codex login --with-api-key
Confirm it’s stored (and which auth mode is active):
codex login status   # or: codex doctor
Already logged into Codex with a stale key from a past login? Run codex logout first, then re-run the codex login --with-api-key command above after setting up your OpenAI API key.
Skipping the frontier planner entirely (using plan-sn)? You don’t need an OpenAI key at all — plan-sn goes through the SambaNova provider.

Wire up SambaNova

Codex reads ~/.codex/config.toml. Add a SambaNova provider and two profiles — one for planning, one for execution: ~/.codex/config.toml (append; don’t replace your existing block):
[model_providers.sambanova]
name = "SambaNova"
base_url = "https://api.sambanova.ai/v1"
env_key = "SAMBANOVA_API_KEY"
wire_api = "responses"

# --- frontier planner (default OpenAI provider) ---
[profiles.plan]
model_provider = "openai"
model = "gpt-5"
approval_policy = "on-request"
sandbox_mode = "workspace-write"

# --- SambaNova planner ---
[profiles.plan-sn]
model_provider = "sambanova"
model = "gpt-oss-120b"
approval_policy = "on-request"
sandbox_mode = "workspace-write"

# --- SambaNova executor ---
[profiles.execute-sn]
model_provider = "sambanova"
model = "MiniMax-M2.7"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
wire_api = "responses" is what makes this work directly — SambaNova’s /v1/responses endpoint matches the OpenAI Responses API shape Codex sends. If you’ve seen older guides recommend LiteLLM as a proxy, you don’t need it.
Then create one demo workspace and reuse it across all three demos:
mkdir -p ~/sambanova-codex-demo && cd ~/sambanova-codex-demo

Demo 1 — SambaNova end-to-end

A pet-friendly “hello world” landing page, built and verified entirely by MiniMax-M2.7 via the execute-sn profile.
codex --profile execute-sn "Create a minimalist, pet-friendly 'hello world' landing page in this directory. One index.html, one style.css, no JS frameworks. Soft pastel palette, a friendly paw-print emoji, a short tagline ('Hello, friend'), and a single call-to-action button. Keep it under 80 lines of HTML+CSS combined. Open the file when done so I can preview it."
Verify:
open index.html
That’s the SN-only baseline. One model, one profile, one call.

Demo 2 — Frontier plans, SambaNova executes

The architect/builder split: the plan profile (frontier model) writes a precise PLAN.md; execute-sn (MiniMax-M2.7) carries it out. PLAN.md is the artifact that crosses the boundary — reproducible, swappable, reviewable. Step 1 — plan with the frontier model:
codex --profile plan "Read index.html and style.css in this directory. Write PLAN.md describing how to extend this landing page into a 'pet adoption finder' demo:
- A gallery of 6 placeholder pet cards (name, species, one-line bio) in CSS grid
- A search input that filters cards by name (vanilla JS, no frameworks)
- A dark-mode toggle that persists in localStorage

Include exact file layout, the JS event handlers needed, and a verification checklist a human can run in the browser. Don't modify any code yet."
Open PLAN.md and review. Edit it freely — that’s the point of materializing the plan. Step 2 — hand PLAN.md to SambaNova:
codex --profile execute-sn "Read PLAN.md and execute every step. After each step, list which acceptance criteria from the plan are now satisfied. Open index.html at the end so I can verify in the browser."
Step 3 — verify:
open index.html
You should see the gallery, working search, and a working dark-mode toggle. The executor never sees the planner’s conversation — PLAN.md is its entire spec. Tweak PLAN.md and rerun the same --profile execute-sn command, or swap the planner profile for plan-sn (no frontier) without rewriting the plan.
Want SambaNova on both sides? codex --profile plan-sn … for the planner uses gpt-oss-120b instead of OpenAI. Useful when you don’t want any frontier dependency.

Demo 3 — MCP-fed planning with live library docs

Demo 2, plus an MCP server. The planner uses Context7 to fetch current docs for a library, bakes them into PLAN.md, and MiniMax executes. Solves the “model trained on stale docs” problem without writing custom retrieval.

Install Context7 as an MCP server

Free API key from context7.com/dashboard, then export it:
export CONTEXT7_API_KEY=ctx7sk-
Register Context7 in ~/.codex/config.toml:
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
env = { "CONTEXT7_API_KEY" = "${CONTEXT7_API_KEY}" }
Free tier works without the key — drop the env line and you’ll just hit lower rate limits.
The MCP server is now available to every profile. Confirm:
codex --profile plan "List the tools you can call from the context7 MCP server."
You should see resolve-library-id and query-docs.

The task

Stamp each pet card from Demo 2 with a human-readable “Added X days ago” label, computed at page load with date-fns (formatDistanceToNow). date-fns is a good Context7 target: its v2→v3 rewrite changed how it’s imported (tree-shakeable named exports, a new UMD cdn.min.js build) and v4 added time-zone support — so models routinely emit stale default-import patterns that don’t run.

Step 1 — plan profile fetches current docs and writes the plan

codex --profile plan "Use the context7 MCP server to look up current docs for the 'date-fns' library — specifically formatDistanceToNow with the addSuffix option, and how to load date-fns in a plain browser page via its UMD CDN build (the dateFns global) vs ESM named imports. Then update PLAN.md with a section 'Phase 2: relative date labels' describing how to give each pet card a fixed data-added ISO date and render an 'Added X days ago' label from it on load. Use the up-to-date API from Context7 — not what you remember. Quote the exact <script> CDN tag, the global function call, and addSuffix usage verbatim from the docs, and include a verification step."
The planner calls resolve-library-idquery-docs, gets today’s API, and writes a plan grounded in current docs.

Step 2 — hand to SambaNova

codex --profile execute-sn "Read PLAN.md 'Phase 2' and execute it. After loading, open index.html and confirm each card shows an 'Added X days ago' label."
The executor doesn’t need MCP — PLAN.md already contains the resolved API. MCP access stays on the (more expensive) planner side, where it pays off.

Step 3 — verify

open index.html
Each of the 6 cards should show an “Added X days ago” label (e.g. “Added 3 days ago”).

Why this matters

This is MCP-fed planning made concrete: the frontier planner has the right context, the SambaNova executor stays cheap and tool-light, and PLAN.md is the boundary.

Tips

  • --profile is the whole knob. Don’t override --model and --provider on the CLI — they bypass the profile and stop being reproducible.
  • One repo, many profiles. Add a [projects."/abs/path/to/repo"] block with trust_level = "trusted" to skip the “trust this folder?” prompt for known dirs.
  • approval_policy = "on-request" is the right default for the executor — the model asks before destructive shell calls. Drop to "never" only inside throwaway sandboxes.
  • Tell the executor to verify (“open index.html and confirm…”) or it will edit and stop.

Common gotchas

401 Unauthorized on SambaNova. env_key = "SAMBANOVA_API_KEY" resolves at the time Codex spawns its HTTP client, so the var must be exported in the shell that launches codex — not just set in a .env. echo $SAMBANOVA_API_KEY before you run. Quota exceeded. Check your plan and billing details. on the plan profile. The openai provider authenticates from ~/.codex/auth.json, not from $OPENAI_API_KEY. A curl that works with your env key proves nothing here — Codex is sending whatever key (or ChatGPT login) is stored in auth.json, which may be stale or out of credits. Fix: codex logout then printenv OPENAI_API_KEY | codex login --with-api-key, and confirm with codex doctor that the stored auth matches the key you intend to bill. wire_api must be responses. Codex only supports wire_api = "responses"; the older wire_api = "chat" value was removed and now errors at startup. SambaNova’s /v1/responses endpoint matches what Codex sends. If a specific model returns 404 on /v1/responses, that model isn’t served over the Responses API — switch to one that is (MiniMax-M2.7, gpt-oss-120b) rather than changing wire_api. model not found. Use the bare SambaNova model id (MiniMax-M2.7, DeepSeek-V3.1, gpt-oss-120b) — Codex prepends nothing. The sambanova/ prefix you may have seen in opencode/AI SDK configs is not used here. Context7 tools missing. mcp_servers is loaded once at startup — if you edited config.toml mid-session, exit and rerun.

Composing with MCP servers

Codex profiles + MCP servers compose cleanly because profiles only swap the model, not the tool surface — every profile sees every registered MCP server:
ProfileModelBest forMCP access
planfrontier (gpt-5, o3, …)reading, reasoning, calling MCPfull
plan-sngpt-oss-120bsame, no frontier dependencyfull
execute-snMiniMax-M2.750–200 turns of edits + testsfull (often unused)
Three patterns fall out: 1. MCP-fed planning. Frontier planner pulls external context (docs, Jira via the Atlassian MCP server, GitHub issues), bakes it into PLAN.md, hands to execute-sn. 2. MCP-driven handoff. After execute-sn finishes, run a follow-up --profile plan call that uses a GitHub or Slack MCP server to open a PR / post a summary — the executor never needs those credentials. 3. Shell-CLI tools inside the executor. execute-sn has shell access under sandbox_mode = "workspace-write". Any CLI on PATH (gh, git, aws, …) is fair game — tell it in the prompt:
Example: codex --profile execute-sn "Implement PLAN.md, run npm test, then run 'gh pr create --fill' to open a draft PR."

References