Skip to content

Codex harness default can suppress direct WebChat final replies #81109

Description

@100yenadmin

TLDR

Codex harness defaults direct source-visible replies to message_tool, which is correct for many external direct-chat routes, but it is wrong for internal WebChat sessions. WebChat is an internal/non-deliverable channel, so a direct WebChat turn can suppress the normal final reply path and steer the model toward message(action=send). The user-visible symptom is a private/tool-send style response such as Sent. instead of the actual answer in the WebChat thread.

Impact

Product impact: P2 if WebChat/direct local OpenClaw sessions are run through Codex by default. Users can lose the visible answer for a normal direct WebChat turn even though the model completed the request.

QA impact: P1 for Codex runtime confidence, because this is exactly the class of first-hour local gateway behavior the runtime parity harness should catch: the wrong delivery layer is selected even though the model/runtime may otherwise be healthy.

What is wrong

extensions/codex/harness.ts sets deliveryDefaults.sourceVisibleReplies = "message_tool" for the Codex harness. dispatch-from-config applies that harness default when direct-chat messages.visibleReplies is unset. For WebChat/internal direct sessions, that default is unsafe because WebChat is not an outbound delivery target for message(action=send).

This is not a request to expose duplicate OpenClaw dynamic workspace tools in Codex. It is a product delivery-policy bug: internal WebChat source replies should stay on the automatic final-reply path.

Evidence

Local beta.5 session logs showed a direct WebChat/Codex turn using message(action=send) and then producing a visible Sent. final reply rather than the substantive answer. Source inspection matches the behavior:

  • extensions/codex/harness.ts defines the Codex harness default as sourceVisibleReplies: "message_tool".
  • src/auto-reply/reply/dispatch-from-config.ts applies harness defaults for direct source-visible replies when config is unset.
  • src/utils/message-channel-constants.ts defines WebChat as the internal message channel.
  • src/infra/outbound/targets-resolve-shared.ts rejects WebChat as an outbound delivery target.

Reproduction

A focused regression test reproduces the policy mismatch:

  1. Register a Codex harness with deliveryDefaults.sourceVisibleReplies = "message_tool".
  2. Create a direct WebChat context with Provider, Surface, and OriginatingChannel set to webchat.
  3. Leave messages.visibleReplies unset.
  4. Dispatch a normal reply.
  5. Expected: sourceReplyDeliveryMode is automatic and the final reply is queued to WebChat.
  6. Actual before fix: the harness default can select message_tool_only, suppressing automatic final delivery.

Proposed fix

Ignore harness sourceVisibleReplies: "message_tool" defaults for internal WebChat source contexts. Keep the Codex harness default for external direct-chat routes where the message tool is the intended visible-reply path.

Validation

Focused local validation on a Lexar-backed checkout:

VITEST_MAX_WORKERS=1 pnpm test src/auto-reply/reply/dispatch-from-config.test.ts -- -t "keeps internal webchat"
VITEST_MAX_WORKERS=1 pnpm test src/auto-reply/reply/dispatch-from-config.test.ts

Both passed locally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions