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:
- build CLI args
- spawn
codex exec
- parse stdout / JSONL / text output
- 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:
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:
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:
- OpenClaw launches Codex with
--output-last-message <file>
- Codex completes
- OpenClaw reads the result artifact
- If artifact text exists, OpenClaw uses it as the final reply payload
- 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.
Summary
OpenClaw's direct
codex-cliexecution path currently relies too heavily on stdout / JSONL / exit status to determine the final user-visible reply.In practice, this creates a reliability gap:
A more reliable contract is available today in Codex CLI itself:
--output-last-message <file>This issue proposes that OpenClaw's
codex-clirunner 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-clidirect runner path is roughly:codex execThat works in many cases, but it has a few reliability problems:
There is already a related bug report in this area:
This issue is related, but narrower and more structural:
Proposed solution
1. Add result-artifact finalization to the direct
codex-clirunnerFor the direct CLI path (
codex-clibackend), automatically allocate a temp file and append:2. Prefer artifact over stdout for the final reply
After the Codex process exits:
output-last-messageartifact if it existspayloads[].text3. 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:
streamartifacthybridwhere
codex-cliwould default toartifactorhybrid, while other runtimes can remainstream.Why this matters
This improves the OpenClaw → exec → Codex CLI → reply chain in a practical way:
Evidence / local validation
I locally validated this design with a package-level runtime hotfix and two kinds of tests.
A. Real direct
codex-cliround-tripUsing OpenClaw's real
codex-cliprovider 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-clibackend that intentionally returned conflicting outputs:STDOUT_ONLY_20260411--output-last-messagefile content:ARTIFACT_WINS_20260411Observed final OpenClaw payload:
ARTIFACT_WINS_20260411This 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:
codex-cliexecution pathsNormal model replies, normal tool calls, and unrelated runtimes do not need to use this mechanism.
Suggested implementation area
Most likely implementation area:
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-cliruns:--output-last-message <file>Impact
Affected users:
codex-cli/*as a direct CLI backendSeverity:
Related
codex-cli/gpt-5.4This proposal complements those issues by making final-result handling deterministic.