#How to have OPENAI_API_KEY used for embedding but not everything else?

1 messages · Page 1 of 1 (latest)

cunning ivy
#

OC keeps writing to ~/.codex/auth.json even though I have a subscription set up

sharp fogBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

raw shoreBOT
warm compassBOT
#

Yep, that can be expected.

If you set up OpenAI Code via “Codex CLI reuse”, OpenClaw treats ~/.codex/auth.json as the external source of truth. When it refreshes the subscription token, it writes the refreshed credential back there. So that behavior does not mean your subscription is being ignored.

Also, for your thread title question: Codex subscription auth does not cover embeddings. So this split is normal:

  • chat/codingopenai-codex/*
  • embeddingsopenai/* with a real OPENAI_API_KEY

If you want OpenClaw to stop touching ~/.codex/auth.json, switch from Codex CLI reuse to native OpenClaw Codex OAuth:

openclaw models auth login --provider openai-codex --set-default

That stores the credential in OpenClaw auth profiles instead of reusing Codex CLI storage.

#

Also worth checking for stale legacy overrides:

openclaw doctor

And please paste:

openclaw --version
openclaw models status

That’ll tell us which auth path you’re actually on.

Docs:

cunning ivy
#

I was only able to get it to stop doing this by removing the api key from the openclaw.json. But now it won't be able to do embeddings

warm compassBOT
#

Yep, that makes sense.

What you want is this split:

  • chat/coding via openai-codex/* using your Codex subscription
  • embeddings via a real OpenAI API key

The clean way is to pin the OpenAI key to memory search only, instead of using it as general OpenAI provider auth.

{
  agents: {
    defaults: {
      model: { primary: "openai-codex/gpt-5.4" },
      memorySearch: {
        provider: "openai",
#
        model: "text-embedding-3-small",
        remote: {
          apiKey: "sk-...",
        },
      },
    },
  },
}

Even better, keep the key in env and just pin the provider:

{
  agents: {
#
    defaults: {
      model: { primary: "openai-codex/gpt-5.4" },
      memorySearch: {
        provider: "openai",
        model: "text-embedding-3-small",
      },
    },
  },
}

with OPENAI_API_KEY set on the gateway host.

Important bit: if you originally set up Codex using Codex CLI reuse, OpenClaw may still write refreshed Codex creds back to ~/.codex/auth.json. That part is separate from embeddings.

So if your goal is:

cunning ivy
#

~/.codex ❯ openclaw models status

🦞 OpenClaw 2026.4.12 (66f57a6) — I'm like tmux: confusing at first, then suddenly you can't live without me.

Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : openai-codex/gpt-5.4
Fallbacks (0) : -
Image model : -
Image fallbacks (0): -
Aliases (0) : -
Configured models (1): openai-codex/gpt-5.4

Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (2): anthropic (1), openai-codex (2)

  • anthropic effective=profiles:~/.openclaw/agents/main/agent/auth-profiles.json | profiles=1 (oauth=0, token=1, api_key=0) | anthropic:manual=token:sk-ant-o...-WocOwAA
  • google effective=models.json:AIzaSyB0...5t9cofug | models.json=AIzaSyB0...5t9cofug | source=models.json: ~/.openclaw/agents/main/agent/models.json
  • lemonade effective=models.json:l...l | models.json=l...l | source=models.json: ~/.openclaw/agents/main/agent/models.json
  • minimax effective=profiles:~/.openclaw/agents/main/agent/auth-profiles.json | profiles=1 (oauth=0, token=0, api_key=1) | minimax:global=sk-api-D...2gW_2V_E
  • openai-codex effective=profiles:~/.openclaw/agents/main/agent/auth-profiles.json | profiles=2 (oauth=2, token=0, api_key=0) | openai-codex:default=OAuth, openai-codex:david@t.tech=OAuth (david@.tech)
  • openrouter effective=env:sk-or-v1...df1cae3d | env=sk-or-v1...df1cae3d | source=env: OPENROUTER_API_KEY
  • perplexity effective=env:sk-or-v1...df1cae3d | env=sk-or-v1...df1cae3d | source=env: OPENROUTER_API_KEY

OAuth/token status

  • anthropic
    • anthropic:manual static
  • openai-codex usage: 5h 98% left ⏱48m · Week 80% left ⏱2d 20h
    • openai-codex:david@t.tech) ok expires in 10d
    • openai-codex:default ok expires in 10d
warm compassBOT
#

Ah, this output helps a lot.

You have two Codex OAuth profiles:

  • openai-codex:default
  • openai-codex:david@t.tech

When there are multiple profiles, OpenClaw can rotate between them unless you pin the auth order. I suspect openai-codex:default is the CLI-synced one, which is why you keep seeing writes to ~/.codex/auth.json.

So I’d do this:

openclaw models auth order set --provider openai-codex 'openai-codex:david@t.tech' openai-codex:default

That should make the explicit email profile win first.

#

For embeddings, since your output says Shell env: off, I would not rely on OPENAI_API_KEY from the shell. Put the key under memorySearch only:

{
  agents: {
    defaults: {
      model: { primary: "openai-codex/gpt-5.4" },
      memorySearch: {
        provider: "openai",
        model: "text-embedding-3-small",
        remote: {
          apiKey: "sk-...",
        },
      },
    },
  },
#
}

So, in short:

  • pin openai-codex:david@t.tech first
  • use memorySearch.remote.apiKey for embeddings
  • keep default model on openai-codex/gpt-5.4

If you want, run this after setting the order:

openclaw models auth order get --provider openai-codex

Docs:

cunning ivy
#

The problem isn't that it's writing oauth to codex/auth.json it was that it was writing the api key

warm compassBOT
#

Ah, got it, thanks, that’s a different problem.

In that case, I’m pretty sure this is not intended behavior. OpenClaw’s Codex refresh path should only update the OAuth token fields in ~/.codex/auth.json, not add an API key there. It preserves an existing OPENAI_API_KEY field if one is already present, but it should not be the thing inventing it.

So the safest workaround is:

  1. Do not put the embedding key in the general OpenAI auth slot
  2. Put it only under memory search config
{
  agents: {
    defaults: {
      model: { primary: "openai-codex/gpt-5.4" },
      memorySearch: {
        provider: "openai",
#
        model: "text-embedding-3-small",
        remote: {
          apiKey: "sk-...",
        },
      },
    },
  },
}

That keeps the OpenAI key scoped to embeddings, instead of making it look like normal openai/* provider auth.

Also, since your status shows Shell env: off, config is the right place here.

If it still re-adds OPENAI_API_KEY to ~/.codex/auth.json after switching to memorySearch.remote.apiKey, I’d call that a bug and ask you to file an issue with:

#
  • openclaw --version
  • your redacted openclaw.json
  • whether OPENAI_API_KEY was already present in ~/.codex/auth.json before the run

Issue tracker: https://github.com/openclaw/openclaw/issues

If you want, paste your redacted OpenClaw config and I can show the exact minimal change.

cunning ivy
#

It doesn't put it in there anymore, but now I can't talk to the model

warm compassBOT
#

Okay, that means we probably fixed the embedding key leak, but now there’s a separate chat auth/routing issue.

Your earlier models status looked fine for Codex chat, so the next thing I need is the exact error text from the failed message.

Also please paste:

openclaw models auth order get --provider openai-codex

Why I’m asking:

  • if the error says No API key found for provider "openai", it’s hitting openai/* instead of openai-codex/*
  • if it says openai-codex with invalid_grant / auth failure, then it’s the Codex profile/order
  • if it says something else, we can narrow it down fast

So, please send:

#
  1. the exact assistant error
  2. the output of openclaw models auth order get --provider openai-codex

I think we’re close.

cunning ivy
warm compassBOT
#

Yep, that error is the clue.

It is not using the native Codex OAuth route there. It is hitting the direct OpenAI Responses API:

https://api.openai.com/v1/responses

That usually means you have a stale/legacy models.providers.openai-codex override in openclaw.json, for example api, baseUrl, or old transport config, and it’s shadowing the built-in Codex OAuth path.

What I’d check next:

  1. Run:
openclaw doctor
  1. Look in openclaw.json for a block like:
#
models: {
  providers: {
    "openai-codex": {
      // api / baseUrl / transport-ish stuff
    }
  }
}

If you have that, remove that whole openai-codex provider override unless you intentionally need a custom proxy.

  1. Restart:
openclaw gateway restart
cunning ivy
#

I was using agents.defaults.embeddedHarness = { runtime: "codex", fallback: "pi" }

warm compassBOT
#

Ah, yep, that’s the missing piece.

You were mixing two different paths:

  • openai-codex/gpt-5.4 = Codex OAuth through normal OpenClaw/PI
  • codex/gpt-5.4 = Codex app-server harness
  • embeddedHarness.runtime: "codex" forces the Codex app-server path

So this combination is the problem:

agents.defaults.embeddedHarness = { runtime: "codex", fallback: "pi" }

If you want subscription auth and only an API key for embeddings, do not force the Codex harness.

Use this shape instead:

#
{
  agents: {
    defaults: {
      model: { primary: "openai-codex/gpt-5.4" },
      embeddedHarness: {
        runtime: "auto",
        fallback: "pi",
      },
      memorySearch: {
        provider: "openai",
        model: "text-embedding-3-small",
        remote: {
          apiKey: "sk-...",
        },
      },
#
    },
  },
}

Or just remove the embeddedHarness override entirely.

Short version:

  • want Codex OAuth subscriptionopenai-codex/*, no forced runtime: "codex"
  • want Codex app-server harnesscodex/*

That 401 from https://api.openai.com/v1/responses is exactly what I’d expect from forcing the Codex app path without the auth it expects.

Docs:

cunning ivy
#

Why wouldn't the codex harness use oauth? And why would OC write the api key to auth.json?

warm compassBOT
#

Because those are two different auth lanes.

  • openai-codex/* uses OpenClaw’s Codex OAuth provider
  • codex/* + embeddedHarness.runtime: "codex" hands execution to the external Codex app-server

The Codex harness does not use OpenClaw’s openai-codex auth profile machinery. It uses whatever auth the Codex app-server itself can see, usually OPENAI_API_KEY and/or Codex CLI state under ~/.codex/*.

So, if you want OpenClaw-managed Codex OAuth, use:

  • openai-codex/gpt-5.4
  • no forced embeddedHarness.runtime: "codex"

On the second part, OpenClaw should not be inventing OPENAI_API_KEY inside ~/.codex/auth.json. The current Codex-file refresh path only updates the OAuth token fields and preserves any existing top-level fields. So if OPENAI_API_KEY showed up there, one of these is true:

  1. it was already there before
  2. the Codex app / Codex CLI wrote it
  3. you hit a bug
cunning ivy
#
  1. it wasn't
  2. possible, but it had to get it from somewhere and if true, OC gave it to it
  3. also possible

harness should be able to use oauth. the whole issue is that codex app was logged in with oauth and when OC would run all of a sudden it would change to api

warm compassBOT
#

I agree with you. It should keep using the Codex app’s OAuth if that’s how Codex is already logged in.

What seems to be happening is:

  • the Codex harness is using the Codex app-server auth surface, not OpenClaw’s openai-codex auth-profile path
  • once an OpenAI API key is available, the Codex side appears to prefer or switch to API-key mode
  • and in your repro, that ends up contaminating ~/.codex/auth.json

So, bluntly, I think this is a bug or design gap, not you misconfiguring it.

Practical reality today:

  • if you want stable Codex OAuth subscription auth, use openai-codex/*
  • if you force embeddedHarness.runtime: "codex", you are in the Codex app-server lane, and that auth behavior is clearly not isolated well enough here

So I’d treat this as issue-worthy with this repro:

#
  1. Codex app logged in via OAuth
  2. OpenClaw configured with embeddedHarness.runtime: "codex"
  3. OpenAI API key present for embeddings
  4. OpenClaw run causes Codex app to switch to API mode / writes API key into ~/.codex/auth.json

Please file it here: https://github.com/openclaw/openclaw/issues

Short-term workaround, sadly:

  • need OAuth for chatopenai-codex/gpt-5.4, no forced Codex harness
  • need Codex harness specifically → avoid exposing that process to an OpenAI API key until this is fixed

If you want, I can help you phrase the GitHub issue cleanly in one message.

cunning ivy
#

yes

warm compassBOT
#

Yep. I’d file it like this:

Title
Codex harness switches Codex app from OAuth to API-key auth when OpenAI key is present for embeddings

Body

## Version

OpenClaw 2026.4.12

## What I expected

I expected to be able to:

- use the Codex app / Codex harness with my existing Codex OAuth login
#
- keep an OpenAI API key available only for embeddings

without OpenClaw changing Codex auth mode.

## What happened

When I configured OpenClaw to use the Codex harness and also had an OpenAI API key available for embeddings, the Codex app appeared to switch from OAuth auth to API-key auth.

I also observed `~/.codex/auth.json` being rewritten so that it contained the OpenAI API key, even though Codex had originally been logged in with OAuth.

After that, Codex harness requests started failing with auth behavior consistent with direct API usage instead of the expected OAuth-backed Codex app behavior.

## Repro

1. Log Codex app in with OAuth
#
2. Configure OpenClaw with:
   ```json5
   agents: {
     defaults: {
       embeddedHarness: { runtime: "codex", fallback: "pi" }
     }
   }
  1. Also configure an OpenAI API key for embeddings
  2. Run OpenClaw through the Codex harness
  3. Observe that Codex auth behavior changes and ~/.codex/auth.json gets updated with the API key

Notes

  • If I avoid the Codex harness and use openai-codex/*, OAuth works as expected