#Codex harness issues

1 messages · Page 1 of 1 (latest)

storm juniper
#

It looks like openclaw is moving towards codex harness as the preferred runtime for OpenAI models

I'm on v2026.5.7. Doctor migrated all my openai-codex models to OpenAI. So now I'm on codex runtime

How can I ensure the codex harness is working properly and that my config is ok. Some issues I'm having:

  • sometimes the model doesn't reply, I tell it I can't see your reply and then it sends the reply through some other way. This happens in DM and group chats
  • the model will be slow to reply, I'll see krilling and then no response
proud nicheBOT
#

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

ember mortarBOT
#

Yep — after that migration, openai/gpt-* + enabled codex plugin is the expected shape. openai-codex should now mainly be the auth profile provider, not the model prefix.

Quick sanity checklist:

  1. In the affected Discord DM/thread/channel, run:
/status
/codex status
/codex models

You want /status to show Runtime: OpenAI Codex. /codex status should show app-server connectivity/account/rate-limit-ish state. If changing runtime/model config, use /new or /reset before testing so the existing session doesn’t keep stale routing.

  1. Config shape should be roughly:
{
  plugins: {
#
    entries: {
      codex: { enabled: true }
    }
  },
  agents: {
    defaults: {
      model: "openai/gpt-5.5" // example: canonical openai/* ref, not openai-codex/*
    }
  }
}

If you use plugins.allow, make sure it includes codex.

  1. Your “typing/krilling but no visible response” symptom very likely matches the visible-replies behavior, not necessarily Codex failing. In Codex mode, final assistant text can finish privately unless the model calls message(action=send). In group/channel rooms this is the default safety posture; Codex also defaults direct chats this way when messages.visibleReplies is unset.

For legacy “always post the final answer visibly” behavior, set:

#
{
  messages: {
    visibleReplies: "automatic",
    groupChat: {
      visibleReplies: "automatic"
    }
  }
}

That’s the first thing I’d try if you want reliable DM + group visible replies while testing.

  1. To confirm the diagnosis, check logs/session output for didSendViaMessagingTool: false. That means the model produced an answer, but didn’t send it through Discord. If instead logs show app-server timeout / no turn/completed, then it’s more of a Codex runtime hang and worth collecting diagnostics.

Useful local checks:

storm juniper
#

Also agent is sending heartbeat_ok to my TG DM instead of suppressing it

ember mortarBOT
#

That one has two likely causes:

  1. Telegram heartbeat OKs are explicitly enabled somewhere. Default is to suppress OKs, so check for this and remove/flip it:
{
  channels: {
    telegram: {
      heartbeat: {
        showOk: false
      }
    }
  }
}

Also check channels.defaults.heartbeat.showOk and channels.telegram.accounts.<accountId>.heartbeat.showOk — per-account beats per-channel beats defaults.

  1. Codex is sending heartbeat_ok via the message tool instead of using the heartbeat response path. Normal heartbeat text filtering should suppress HEARTBEAT_OK/heartbeat_ok-style acks, but if the model explicitly calls message(action=send) to your TG DM, it can bypass the “silent OK” intent. In Codex heartbeat turns, the preferred path is heartbeat_respond with notify: false.
#

So I’d check, in order:

openclaw config get channels.telegram.heartbeat
openclaw config get channels.defaults.heartbeat
openclaw config get agents.defaults.heartbeat
openclaw system heartbeat last
openclaw logs --follow

If logs show an outbound Telegram send from the message tool, make sure heartbeat_respond isn’t excluded by your tool policy. If you use tools.allow, include real tool names/groups such as heartbeat_respond or an appropriate group, not old-style names.

Docs: https://docs.openclaw.ai/gateway/heartbeat

storm juniper
#

re heartbeat, here is my output

Config path not found: channels.telegram.heartbeat
server@server:~$ openclaw config get channels.defaults.heartbeat

🩞 OpenClaw 2026.5.7 (eeef486) — Deployed locally, trusted globally, debugged eternally.

Config path not found: channels.defaults.heartbeat
server@server:~$ openclaw config get agents.defaults.heartbeat

🩞 OpenClaw 2026.5.7 (eeef486) — Say "stop" and I'll stop—say "ship" and we'll both learn a lesson.

{
"every": "30m",
"activeHours": {
"start": "07:00",
"end": "23:00"
},
"model": "openai/gpt-5.4-mini",
"target": "telegram",
"directPolicy": "allow",
"to": "MASKED"
}

ember mortarBOT
#

Yep — that output means the heartbeat config is under the right place: agents.defaults.heartbeat.

channels.telegram.heartbeat / channels.defaults.heartbeat being “not found” just means you don’t have channel-level heartbeat visibility overrides configured there. The scheduler itself is agent-level.

Your current effective setup is:

  • run every 30m
  • only between 07:00 and 23:00 in the configured/user/host timezone
  • use model openai/gpt-5.4-mini
  • deliver to Telegram via target: "telegram" + to: "MASKED"
  • allow direct delivery with directPolicy: "allow"

If it still isn’t sending, the next things I’d check are:

  1. Is HEARTBEAT.md empty/header-only? If yes, OpenClaw intentionally skips to save tokens.
  2. Are you outside active hours because of timezone? Add activeHours.timezone if you want it explicit.
  3. Look for skip reasons like quiet-hours, empty-heartbeat-file, no-tasks-due, alerts-disabled, or unknown accountId.

Docs: https://docs.openclaw.ai/gateway/heartbeat

storm juniper
#

its sending but i can see heartbeat_ok in my TG dm. i thought that should be suppressed...

#

/codex status results

Codex app-server: connected
Models: gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, gpt-5.3-codex-spark, gpt-5.2
Account: MASKED
Rate limits: Codex: primary 1%, resets in 5 hours 2026-05-10T12:24:35.000Z, secondary 20%, resets in 2 days 2026-05-11T22:54:35.000Z; GPT 5.3 Codex Spark: primary 0%, resets in 5 hours 2026-05-10T12:27:39.000Z, secondary 0%, resets in 7 days 2026-05-17T07:27:39.000Z
MCP servers: 1
Skills: 1

ember mortarBOT
#

You’re right that it should be suppressed — but the token matching path I checked is case-sensitive.

So if Telegram is literally showing heartbeat_ok lowercase, that won’t be recognized as the ack token. The suppressible token is exactly:

HEARTBEAT_OK

That explains the behavior. Two fixes:

  1. Make your heartbeat prompt stricter, e.g. “If nothing needs attention, reply exactly HEARTBEAT_OK in uppercase, with no other text.”
  2. If the model still lowercases it, use a more obedient heartbeat model or file a bug/feature request for case-insensitive ack stripping: https://github.com/openclaw/openclaw/issues

If you’re seeing uppercase HEARTBEAT_OK and it still sends, then I’d check channel visibility next — specifically whether channels.telegram.accounts.<accountId>.heartbeat.showOk or channels.telegram.heartbeat.showOk is true. But from what you pasted earlier, lowercase is probably the culprit.

#

That status points pretty strongly at rate limits, not a connection/auth problem.

Codex app-server: connected means the harness can reach Codex. But your usable quota is basically gone:

  • Codex primary: 1%, resets in ~5h
  • Spark: 0%, resets in ~5h / secondary in 7d

So if runs are failing, stalling, or falling back weirdly, I’d treat this as quota exhaustion first. Wait for the primary reset, or switch to a non-exhausted model/account if you have one configured.

One extra note: your heartbeat config using openai/gpt-5.4-mini may still draw from that same Codex/OpenAI-side allowance depending on auth/provider routing, so heartbeats can nibble at the remaining quota too. If you’re debugging Codex harness stuff, I’d temporarily set heartbeat to every: "0m" or use a cheaper/separate provider for heartbeat until the quota recovers.

storm juniper
#

no - im seeing HEARTBEAT_OK

also codex limits you're reading wrong. on codex windows app i see 99% remaining, so its 1 % used

ember mortarBOT
#

Ah, yep — I was wrong on both counts. Thanks for catching it.

Codex status: you’re right, that reads as used, not remaining. So primary 1% = ~99% remaining. Not a quota problem. 🩞

For uppercase HEARTBEAT_OK: agreed, that should normally be suppressed. If it’s being delivered, the most likely cause is heartbeat visibility being enabled at a more specific Telegram account level.

The precedence is:
channels.telegram.accounts.<accountId>.heartbeat → channels.telegram.heartbeat → channels.defaults.heartbeat → default

You already checked the middle/default paths. Please check the per-account path, but don’t paste tokens or full account config:

openclaw config get channels.telegram.accounts.default.heartbeat

If your Telegram account id is not default, replace default with that account id.

#

If that returns something like:

{ "showOk": true }

that explains it. Set it false/remove it, e.g. conceptually:

channels: {
  telegram: {
    accounts: {
      default: {
        heartbeat: { showOk: false }
      }
    }
#
  }
}

If the account-level path is also not found / false, then I’d suspect a bug in the Telegram heartbeat delivery path and it’s worth filing with your version + config snippets: https://github.com/openclaw/openclaw/issues

storm juniper
#

server@server:~$ openclaw config get channels.telegram.accounts.default.heartbeat

🩞 OpenClaw 2026.5.7 (eeef486) — I'll butter your workflow like a lobster roll: messy, delicious, effective.

Config path not found: channels.telegram.accounts.default.heartbeat

#

no results for cat openclaw.json | grep -i showok

ember mortarBOT
#

Good, that rules out the account-level showOk path too. And yes: if the delivered text is exactly uppercase HEARTBEAT_OK, with no media attached, and no showOk: true, it should be suppressed.

Two remaining likely causes:

  1. A per-agent heartbeat override is changing behavior. Check:
openclaw config get agents.list

Look for any heartbeat block, especially includeReasoning: true, ackMaxChars, or a different target/account.

  1. It’s a bug/regression in 2026.5.7. The source/tests expect Telegram HEARTBEAT_OK to be dropped when showOk is false/missing.

Can you grab the heartbeat log line after the next one fires?

openclaw logs --limit 300 --plain | grep -i heartbeat
#

The useful bit is whether it says something like status: ok-token with silent: true/false, or whether it treats the message as a normal alert/send. Redact chat ids/tokens, but the heartbeat status/reason fields are safe and should tell us which branch it hit.

#

Yep — no showOk in openclaw.json means it should inherit the default, which is showOk: false. So this is not a visible config opt-in.

At this point I’d stop chasing showOk and check which heartbeat branch the gateway thinks it’s taking. After the next TG HEARTBEAT_OK, run:

openclaw logs --limit 500 --plain | grep -i heartbeat

What we’re looking for:

  • status: ok-token + silent: true → OpenClaw thought it suppressed it, but Telegram delivery still happened = delivery bug.
  • status: ok-token + silent: false → something resolved showOk true despite config not showing it = visibility resolution bug/config source mismatch.
  • status: sent / normal send path → ack stripping didn’t recognize the reply as a pure heartbeat ack.

Also worth checking:

#
openclaw config get agents.list

If any agent has a heartbeat block, only those agents run heartbeats and that per-agent block can change things. Don’t paste secrets/targets, just whether there’s a heartbeat override and fields like includeReasoning, ackMaxChars, target, accountId.

storm juniper
#

also why does codex status say mcp servers:1 and skills:1

what are those mcps and skills? i have many more skills in my skill folder and i dont use mcps

ember mortarBOT
#

Those counts are from Codex’s own environment, not OpenClaw’s skill system.

MCP servers: 1 means Codex sees one MCP server configured somewhere it reads config from. Codex reads MCP config from:

  • ~/.codex/config.toml
  • project-local .codex/config.toml for trusted projects
  • possibly an installed Codex plugin that bundles MCP config

To see which one, in Codex use:

/mcp

or from a shell:

codex mcp list

Skills: 1 means Codex sees one Codex skill available to that session. It does not mean “all OpenClaw skills installed”. Codex scans different locations, mainly:

#
  • repo/current dir: .agents/skills
  • user: ~/.agents/skills
  • admin: /etc/codex/skills
  • bundled Codex system skills

So if your “many skills” are in an OpenClaw skill folder, Codex won’t count those unless they’re also installed in Codex’s skill paths and have valid SKILL.md metadata.

To inspect skills in Codex, use:

/skills

Docs: https://developers.openai.com/codex/mcp and https://developers.openai.com/codex/skills

storm juniper
#

[
{
"id": "main",
"default": true,
"workspace": "/home/server/.openclaw/workspace",
"heartbeat": {
"every": "30m",
"activeHours": {
"start": "07:00",
"end": "23:00"
},
"model": "openai/gpt-5.4-mini",
"session": "agent:main:main",
"target": "telegram",
"directPolicy": "allow",
"to": "MASKED",
"prompt": "Read HEARTBEAT.md if it exists. Only report explicit pending work that needs user attention now. Do not infer tasks from previous chats, repeated heartbeat messages, shared workspace files, or stale session history. If nothing explicitly needs attention, reply exactly HEARTBEAT_OK.",
"ackMaxChars": 300,
"lightContext": true,
"isolatedSession": true,
"skipWhenBusy": true
},

ember mortarBOT
#

That agent config looks sane too — nothing there should make HEARTBEAT_OK visible.

Notably:

  • no includeReasoning: true
  • ackMaxChars: 300 should suppress a bare HEARTBEAT_OK
  • lightContext / isolatedSession / skipWhenBusy don’t explain visible OKs
  • no showOk anywhere means default should be silent

So I’d call this likely a bug/regression unless the logs show otherwise.

For a practical workaround, change the prompt to prefer the heartbeat tool when available:

Read HEARTBEAT.md if it exists. Only report explicit pending work that needs user attention now. Do not infer tasks from previous chats, repeated heartbeat messages, shared workspace files, or stale session history. If heartbeat_respond is available and nothing needs attention, call heartbeat_respond with notify=false. Otherwise, reply exactly HEARTBEAT_OK.

That avoids relying on text-token stripping when the model/tool path supports structured heartbeat responses.

#

But please still grab the logs after one visible HEARTBEAT_OK:

openclaw logs --limit 500 --plain | grep -i heartbeat

If it shows ok-token with silent: true while Telegram got a DM, that’s a very clean bug report for GitHub.

storm juniper
#

this is codex harness in openclaw. codex mcp list is not valid command

ember mortarBOT
#

You’re right — my bad. I answered as if you were using the standalone Codex CLI/app. This is the OpenClaw bundled Codex app-server harness, so codex mcp list is not the right command.

For OpenClaw’s harness, use the chat commands:

/codex mcp
/codex skills

Those are documented harness commands; /codex status only shows the counts. /codex mcp should list the Codex app-server MCP server status, and /codex skills should list the Codex app-server skills.

Also: those counts are Codex app-server native inventory, not necessarily your OpenClaw skill folder. The harness has its own boundary:

  • OpenClaw dynamic tools are exposed to Codex under the openclaw namespace/search path, not counted as Codex “skills”.
  • Native Codex plugins/apps can bring their own MCP/skills.
  • The bundled Codex harness itself can have native capabilities even if you didn’t configure standalone MCPs.

Docs: https://docs.openclaw.ai/plugins/codex-harness

storm juniper
#

ok i changed my heartbeat prompt to that

#

now what about the message replies setting, what should i set it to. whats the default behaviour, whats reccomended setting

ember mortarBOT
#

For the setting we’re talking about, it’s:

messages: {
  groupChat: {
    visibleReplies: "message_tool"
  }
}

Default/current recommended behavior for group/channel rooms is:

visibleReplies: "message_tool"

Meaning: the agent’s normal final answer is private/suppressed in the room, and it only speaks visibly if it explicitly calls the message tool. That’s safer for Discord/Telegram groups because the agent can lurk/process context without accidentally dumping every final answer into the channel.

#

Use this unless your model/runtime is bad at tool calls. If you see logs where the assistant clearly wrote an answer but nothing appeared, and didSendViaMessagingTool: false, then switch to legacy mode:

messages: {
  groupChat: {
    visibleReplies: "automatic"
  }
}

My recommendation for your Codex harness setup: keep group chats on message_tool. For DMs, I’d leave global messages.visibleReplies unset unless you specifically want tool-only delivery everywhere. Codex direct chats may already default that way in harness mode, but groupChat is the important one.

Docs: https://docs.openclaw.ai/channels/groups

storm juniper
#

i only havve groupchat set, nothing set for dms, does that inherit default of automatic?

ember mortarBOT
#

Yes — if you only set:

messages: {
  groupChat: {
    visibleReplies: "message_tool"
  }
}

then that setting applies only to group/channel rooms.

For DMs, messages.visibleReplies is still unset, so normal direct-message behavior applies: replies are visible/automatic unless the active runtime overrides the unset default.

One wrinkle: the Codex harness docs say Codex-mode direct chats may choose message_tool as their unset default. So practically:

  • Groups/channels: your explicit messages.groupChat.visibleReplies wins.
#
  • DMs: no inheritance from groupChat; they use messages.visibleReplies if set, otherwise runtime/channel default.

My recommendation: leave DMs unset unless you have a specific reason to force tool-only behavior everywhere. Explicitly set only groupChat for safety.

storm juniper
#

my issue is in dms the agent doestn visibily respond

ember mortarBOT
#

Ah — then yes, for Codex harness DMs you probably want to set the global direct/source default explicitly:

messages: {
  visibleReplies: "automatic",
  groupChat: {
    visibleReplies: "message_tool"
  }
}

Why: with Codex harness, if messages.visibleReplies is unset, direct chats can default to message_tool. That means the agent may finish the Codex turn privately and only visibly respond if it calls message(action="send"). Great for tool-reliable setups, annoying if it’s silently answering in DMs.

Recommended for your current issue:

  • DMs: messages.visibleReplies: "automatic"
  • groups/channels: keep messages.groupChat.visibleReplies: "message_tool"
storm juniper
#

any command to set that or do i have to edit my config

ember mortarBOT
#

You can set it with openclaw config set — no manual edit needed.

Run:

openclaw config set messages.visibleReplies automatic

Keep your group setting as-is:

openclaw config get messages.groupChat.visibleReplies

You want the end state to be roughly:

#
messages: {
  visibleReplies: "automatic",
  groupChat: {
    visibleReplies: "message_tool"
  }
}

Gateway should hot-reload messages config after saving, so usually no restart needed. If DMs still don’t visibly reply after that, restart the gateway once and test again.

Docs: https://docs.openclaw.ai/cli/config

storm juniper
#

i want to be able to control my codex windows app via openclaw and see chats appear in the codex windows app. is that possible?

is it also possible to run codex on same machine as openclaw and have discord / tg as the chat interface

what are the pros and cons to this. is this using acpx?

ember mortarBOT
#

Short version: Discord/TG as the chat UI for Codex via OpenClaw: yes. Driving the actual Codex Windows app UI and having chats appear inside that app: not really / not the normal supported path.

OpenClaw’s Codex harness talks to Codex app-server, not the Codex Windows GUI. OpenClaw owns the channel routing and transcript mirror; Codex owns the native thread/model loop. With the normal bundled setup, OpenClaw launches a managed app-server and isolates CODEX_HOME/HOME per OpenClaw agent, so its Codex threads/skills/config are scoped to OpenClaw — they won’t necessarily show up in your personal Codex Windows app.

What is supported:

  • Use Telegram/Discord as the interface to Codex-backed turns.
  • Use /codex status, /codex models, /codex threads, /codex resume, /codex steer, /codex stop from chat.
  • Run OpenClaw and Codex app-server on the same machine, using the bundled codex plugin.
  • Optionally connect OpenClaw to an already-running app-server over WebSocket, if you deliberately run one and configure plugins.entries.codex.config.appServer.transport: "websocket" + url.

What I would not expect:

  • “I chat in Discord and the same conversation appears in the Codex Windows app UI.”
  • “OpenClaw remote-controls the Windows Codex app window.”

For your second question: yes, running Codex on the same machine as OpenClaw and using Discord/TG as the chat interface is exactly the native Codex harness use case. Use openai/gpt-* model refs with the bundled codex plugin enabled.

Pros:

#
  • ChatGPT/Codex subscription-backed agent turns from Discord/TG.
  • Persistent Codex native threads, resume/steer/stop controls.
  • Codex-native tool continuation/compaction.
  • OpenClaw still gives you channels, heartbeats, message routing, dynamic tools, etc.

Cons:

  • Not the same UX/transcript as the Codex Windows app.
  • More moving pieces: Gateway + channel bot + Codex app-server + auth.
  • Tool-only visible replies can be surprising until configured, like your DM issue.
  • Local app-server defaults can be powerful/trusted; review sandbox/approval mode if you don’t want YOLO behavior.

Is this ACPX? No, not by default. The normal Codex harness is the bundled native Codex app-server path: /codex ... and openai/gpt-*. ACPX is the external-harness path (/acp ..., runtime: "acp", agentId: "codex") and is mainly for explicitly running external harnesses through ACP.

Docs:
https://docs.openclaw.ai/plugins/codex-harness
https://docs.openclaw.ai/concepts/agent-runtimes
https://docs.openclaw.ai/tools/acp-agents

storm juniper
#

so whats the difference between using codex harness in openclaw and having codex npm installed on same box

ember mortarBOT
#

Think of them as two different layers:

Codex npm installed on the box

  • Gives you the standalone codex CLI / app-server binary on that machine.
  • You can run it manually in a terminal.
  • It uses your normal Codex home/config/auth unless you override it.
  • OpenClaw does not automatically become wired to that install just because it exists.

Codex harness in OpenClaw

  • OpenClaw uses the bundled codex plugin to run agent turns through Codex app-server.
  • Telegram/Discord/etc become the chat UI.
  • OpenClaw owns routing, sessions, channel delivery, heartbeats, message tools, approvals bridge, transcript mirror.
  • Codex owns the native model loop, native thread, native tools, compaction.
  • By default, OpenClaw launches a managed Codex app-server binary, not necessarily the codex npm command on your PATH.
  • It sets isolated CODEX_HOME / HOME per OpenClaw agent, so Codex config/threads/skills are scoped to OpenClaw rather than your personal CLI install.

So installing codex npm is like having the engine available locally. Using the OpenClaw Codex harness is OpenClaw actually wiring that engine into Discord/TG sessions with OpenClaw’s routing/tools around it.

#

You only point OpenClaw at your own installed Codex/app-server if you explicitly configure plugins.entries.codex.config.appServer.command or transport: "websocket". Normal recommended setup: let the bundled plugin manage it.

storm juniper
#

currently im using codex harness, i didnt manually install codex on the same box

anyway to make the codex harness faster?

ember mortarBOT
#

Yes — a few knobs can make Codex harness feel faster. You don’t need to manually install Codex npm for this; the bundled harness already manages the app-server.

Best options, in order:

  1. Turn on priority / fast mode

For the current chat, try:

/fast on

Then check:

/fast status
#

For config-level priority, either set per model:

openclaw config set agents.defaults.models '{"openai/gpt-5.5":{"params":{"fastMode":true}}}' --strict-json --merge

or set Codex app-server service tier:

openclaw config set plugins.entries.codex.config.appServer.serviceTier priority

priority is the “fast lane” setting for native Codex/OpenAI endpoints.

  1. Use a smaller model for routine stuff

If you don’t need max capability every turn, use gpt-5.4-mini or similar for the agent / heartbeat, and save gpt-5.5 for hard tasks. Smaller model = noticeably snappier.

#
  1. Keep threads short

Long Codex threads get slower. If a chat has a lot of history, use:

/codex compact

or start fresh with:

/new
  1. Avoid guardian/approval mode if you want speed

Local stdio Codex harness defaults to the fast trusted-local posture (approvalPolicy: "never", sandbox: "danger-full-access") unless local requirements force guardian mode. Guardian/workspace-write/auto-review is safer, but slower.

storm juniper
#

doesnt fast use more of my quota. whats difference between fast and servicetier priority

ember mortarBOT
#

Yes — assume fast/priority uses the faster priority lane/quota, even if it doesn’t necessarily use more tokens. It can burn through the “priority/fast” bucket faster or hit stricter priority rate limits. So I would not leave it on for heartbeats or casual low-value turns.

Difference:

fastMode: true / /fast on

  • OpenClaw convenience toggle.
  • Session-friendly: /fast on|off|status can change it for the current chat.
  • For OpenAI/Codex, OpenClaw maps it to service_tier = "priority".
  • It does not change reasoning or verbosity.
  • If an explicit serviceTier is already set, OpenClaw preserves that instead of overriding it.

serviceTier: "priority"

  • The lower-level/provider setting itself.
  • More explicit and config-level.
  • Supported values are auto, default, flex, priority.
  • For Codex harness, plugins.entries.codex.config.appServer.serviceTier: "priority" asks the app-server to use that tier.
#

So practically:

  • Use /fast on when you want a specific session temporarily faster.
  • Use serviceTier: "priority" if you want a persistent default.
  • Use default/unset for quota conservation.
  • Keep heartbeat on a cheaper/slower model/tier unless you really need urgent heartbeat work.

My recommendation for your setup: don’t globally force priority yet. Use /fast on only in active DMs/threads where latency matters, and leave heartbeat/default traffic off the priority lane.

storm juniper
#

any other things to know about codex harness that are worth enabling / setting. given openclaw i smoving towards using codex harness as default for openai models

ember mortarBOT
#

Yeah — if you’re leaning into Codex harness as the default OpenAI path, I’d set a few things deliberately rather than just accepting all implicit defaults.

My recommended baseline:

{
  plugins: {
    entries: {
      codex: {
        enabled: true
      }
    }
  },
  agents: {
    defaults: {
      model: "openai/gpt-5.5"
#
    }
  },
  messages: {
    visibleReplies: "automatic",
    groupChat: {
      visibleReplies: "message_tool"
    }
  }
}

Things worth considering:

  1. Fail closed to Codex

If you want OpenAI models to fail instead of silently falling back to another runtime when Codex is unavailable:

#
models: {
  providers: {
    openai: {
      agentRuntime: { id: "codex" }
    }
  }
}

Good for predictable deployments. Slight downside: less graceful fallback.

  1. DM reply behavior

You already hit this one. For Codex harness DMs, set:

#
openclaw config set messages.visibleReplies automatic

Keep groups/channels on message-tool mode for safety:

openclaw config set messages.groupChat.visibleReplies message_tool
  1. Heartbeat prompt using heartbeat_respond

Worth keeping. Codex heartbeat turns expose heartbeat_respond through tool search, so structured quiet/notify is better than relying on final text token stripping.

  1. Don’t globally enable priority unless you mean it

Use /fast on per active session when you care about latency. I wouldn’t set global serviceTier: "priority" for heartbeats/casual traffic unless quota isn’t a concern.

#
  1. Use /codex diagnostics commands

Handy commands:

/codex status
/codex models
/codex threads
/codex compact
/codex diagnostics <note>

If a thread gets slow/weird, try /codex compact or /new before changing half your config.

  1. Leave dynamic tools as searchable

Default is good:

#
codexDynamicToolsLoading: "searchable"

Only use "direct" for debugging/custom app-server issues. Direct loading makes the initial tool context heavier.

  1. Auth/config isolation: know it exists

OpenClaw’s managed Codex app-server uses isolated CODEX_HOME/HOME per agent. That’s good for OpenClaw, but it means personal Codex CLI skills/plugins/config don’t automatically carry over. If you need them:

openclaw migrate codex --dry-run

Then selectively apply what you actually want.

  1. Security posture
#

Local Codex harness defaults are intentionally trusted/local and fast. If you want more review/sandboxing, set guardian mode:

openclaw config set plugins.entries.codex.config.appServer.mode guardian

Tradeoff: safer, but slower/more friction.

My actual recommendation for you: explicit Codex runtime, DMs automatic, groups message-tool, heartbeat via heartbeat_respond, leave priority off globally, and use /codex compact//new for slow threads. That’s the least surprising setup.

storm juniper
ember mortarBOT
#

Yes — with one important distinction.

Codex handles AGENTS.md itself through its native project-doc discovery. OpenClaw does not duplicate/inject AGENTS.md as a synthetic prompt file for Codex harness turns.

But OpenClaw does forward the other workspace bootstrap files through Codex developer instructions on thread/start / thread/resume, including:

  • SOUL.md
  • TOOLS.md
  • IDENTITY.md
  • USER.md
  • HEARTBEAT.md
  • BOOTSTRAP.md
  • MEMORY.md

So: AGENTS.md = Codex-native discovery. Other OpenClaw persona/profile/bootstrap files = forwarded by the harness for workspace parity.

Docs: https://docs.openclaw.ai/plugins/codex-harness-reference#workspace-bootstrap-files

storm juniper
#

Does using codex harness create different working directories . I'm used to openclaw workspace directory structure. Do I need to do anything differently if using codex harness

ember mortarBOT
#

Mostly no — you can keep thinking in terms of the normal OpenClaw agent workspace.

There are two separate “directories” concepts:

  1. OpenClaw workspace / project files

This is still your agent workspace, e.g.

agents.list[].workspace: "/home/server/.openclaw/workspace"

That’s where your AGENTS.md, SOUL.md, HEARTBEAT.md, etc. live. Codex harness still uses that context: Codex discovers AGENTS.md natively, and OpenClaw forwards the other bootstrap files for parity.

  1. Codex home / app-server state

For local managed Codex app-server launches, OpenClaw sets isolated CODEX_HOME and HOME per OpenClaw agent. That affects Codex-native config/accounts/skills/plugins/thread state. It does not mean your normal OpenClaw workspace moved.

#

So day-to-day: you generally don’t need to do anything differently.

The one thing to watch is the working directory for Codex thread binding. /codex bind can take a cwd:

/codex bind --cwd /path/to/project

If you omit it, Codex uses the configured plugins.entries.codex.config.appServer.defaultWorkspaceDir, or the current process directory if that isn’t set.

If you want predictable behavior, set it explicitly:

openclaw config set plugins.entries.codex.config.appServer.defaultWorkspaceDir /home/server/.openclaw/workspace

or bind specific project chats with --cwd.

#

My recommendation: keep your OpenClaw workspace structure as-is. If you use Codex for actual repo work, bind each chat/thread to that repo with /codex bind --cwd /path/to/repo; if it’s general assistant chat, point defaultWorkspaceDir at your OpenClaw workspace.

storm juniper
#

I'm just using codex harness as openclaw documentation says it's the preferred runtime for OpenAI models

ember mortarBOT
#

Yep, that’s the right mental model: if you’re using OpenAI models in OpenClaw, the Codex harness is the preferred/default-ish path now.

In that case I would not over-customize the workspace bits. Keep your normal OpenClaw workspace exactly how you already use it:

agents.list[].workspace: "/home/server/.openclaw/workspace"

Codex harness will still pick up the relevant OpenClaw context. The main difference is internal: OpenClaw gives Codex an isolated Codex home for app-server state, auth/thread metadata/skills/plugins. That’s separate from your OpenClaw workspace and usually not something you need to touch.

I’d only set defaultWorkspaceDir if Codex is starting in a surprising cwd, or if you want /codex bind without --cwd to always land somewhere specific. Otherwise, leave it alone.

For your “normal OpenClaw assistant over Telegram/Discord” setup, the important settings are more like:

messages: {
#
  visibleReplies: "automatic",
  groupChat: { visibleReplies: "message_tool" }
}


and then use openai/gpt-* model refs, not openai-codex/gpt-*. That’s the preferred Codex harness shape.

storm juniper
#

Why is codex harness preferred now? Whatd different from PI and am I gaining something by using codex harness or not

ember mortarBOT
#

Codex harness is preferred for OpenAI models because it lets Codex own the OpenAI agent loop instead of OpenClaw trying to emulate that loop through PI.

The practical difference:

PI runtime

  • OpenClaw owns the model loop directly.
  • OpenClaw sends provider requests, handles tool calls, transcript, compaction, etc.
  • Works well across many providers.
  • For OpenAI/Codex subscription-style usage, it’s less native: OpenClaw has to adapt OpenAI behavior into its own loop.

Codex harness

  • OpenClaw still owns Telegram/Discord routing, sessions, delivery, heartbeats, OpenClaw tools, approvals bridge, transcript mirror.
  • But Codex app-server owns the native OpenAI/Codex thread, tool continuation, compaction, model behavior, and account/model catalog.
  • It’s closer to “how OpenAI expects Codex agent turns to run.”

What you gain:

  • Better alignment with ChatGPT/Codex subscription auth and model availability.