Skip to content

Enhancement: finalize codex-cli replies from --output-last-message artifact instead of relying on stdout #65074

@Wpoithge

Description

@Wpoithge

Summary

OpenClaw's direct codex-cli execution path currently relies too heavily on stdout / JSONL / exit status to determine the final user-visible reply.

In practice, this creates a reliability gap:

  • Codex can finish successfully but the final result is not surfaced in the most stable way
  • stdout and structured stream output are useful, but not always the best source of truth for the final answer
  • automation/orchestration ends up needing extra glue to know what the real final result was

A more reliable contract is available today in Codex CLI itself:

  • --output-last-message <file>

This issue proposes that OpenClaw's codex-cli runner should use that artifact as the finalization source of truth for the final reply payload, instead of depending primarily on stdout / JSONL / exit code.

Problem

Today the codex-cli direct runner path is roughly:

  1. build CLI args
  2. spawn codex exec
  3. parse stdout / JSONL / text output
  4. return final payloads to OpenClaw

That works in many cases, but it has a few reliability problems:

  • stdout can contain progress-oriented or transport-oriented output rather than the clean final answer
  • exit code alone is not enough to determine semantic success/failure
  • downstream orchestrators still need a stable "final answer" contract
  • when the final result is not surfaced cleanly, users can end up asking follow-up questions like "did it finish?" or "what was the result?"

There is already a related bug report in this area:

This issue is related, but narrower and more structural:

For successful or quasi-successful Codex CLI runs, OpenClaw should have a deterministic final result source, and that source should be the --output-last-message artifact.

Proposed solution

1. Add result-artifact finalization to the direct codex-cli runner

For the direct CLI path (codex-cli backend), automatically allocate a temp file and append:

--output-last-message <temp-file>

2. Prefer artifact over stdout for the final reply

After the Codex process exits:

  • first parse stdout / JSONL as today
  • then read the output-last-message artifact if it exists
  • if artifact text is non-empty, use it as the final payloads[].text
  • clean up the temp file afterward

3. Keep stdout/JSONL for process telemetry, but not as the primary final-answer source

This preserves the existing stream/debug behavior while making final result handling deterministic.

4. Optionally expose a generic finalization strategy contract

A more general version of this idea is:

  • stream
  • artifact
  • hybrid

where codex-cli would default to artifact or hybrid, while other runtimes can remain stream.

Why this matters

This improves the OpenClaw → exec → Codex CLI → reply chain in a practical way:

  • more reliable final replies
  • less ambiguity between progress output and final result
  • better orchestration behavior
  • cleaner UX in long-running or delegated coding tasks
  • more robust automation than relying on stdout/exit status alone

Evidence / local validation

I locally validated this design with a package-level runtime hotfix and two kinds of tests.

A. Real direct codex-cli round-trip

Using OpenClaw's real codex-cli provider path, I was able to route a run through Codex CLI and receive the final payload back through OpenClaw successfully.

B. Strong artifact-vs-stdout conflict test

I also built an isolated test gateway / state root and ran a fake codex-cli backend that intentionally returned conflicting outputs:

  • stdout / parsed JSON text: STDOUT_ONLY_20260411
  • --output-last-message file content: ARTIFACT_WINS_20260411

Observed final OpenClaw payload:

  • ARTIFACT_WINS_20260411

This confirms that an artifact-preferred finalization path is practical and works exactly as intended.

Scope

This request is not about changing all providers or all conversations globally.

It should be scoped to:

  • direct codex-cli execution paths
  • and optionally other CLI backends that explicitly support a stable final-result artifact

Normal model replies, normal tool calls, and unrelated runtimes do not need to use this mechanism.

Suggested implementation area

Most likely implementation area:

  • the direct CLI runner path (runCliAgent(...) / CLI backend argument builder / final output parsing path)

This seems like a better fit than ACP protocol internals, because this is specifically a CLI-backend finalization problem.

Expected behavior after fix

For codex-cli runs:

  1. OpenClaw launches Codex with --output-last-message <file>
  2. Codex completes
  3. OpenClaw reads the result artifact
  4. If artifact text exists, OpenClaw uses it as the final reply payload
  5. The user receives the stable final answer without needing manual log-followup

Impact

Affected users:

  • people using codex-cli/* as a direct CLI backend
  • users delegating coding tasks to Codex via OpenClaw
  • anyone wanting more reliable final-result handling for Codex CLI automation

Severity:

  • medium to high as a reliability / UX gap
  • especially noticeable in delegated coding flows and follow-up-heavy sessions

Related

This proposal complements those issues by making final-result handling deterministic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions