Bug type
Behavior bug (incorrect routing / silent non-delivery)
Summary
A Signal direct-session user turn can be processed by a Codex/vscode/internal runner surface and produce the correct final assistant answer, but that final answer is not delivered back to the original Signal recipient unless the assistant explicitly calls the message tool.
This is a wrong-surface/silent-drop variant of the routing bugs tracked around async/internal followups. The answer exists, but the user never receives it in Signal.
Expected behavior
If an inbound turn originated from Signal, the normal final assistant response should be delivered back to that Signal channel/target, even when the active runner/surface is Codex, vscode, webchat, an inter-session event, or another internal execution context.
The delivery invariant should be tied to the original inbound channel/target for the turn, not whichever UI/runner surface happens to own the model execution.
Actual behavior
In the observed incident:
- The user sent two Signal messages.
- OpenClaw processed them inside a Codex/vscode-style rollout/internal session.
- The model generated the correct final answer.
- No explicit message(channel="signal", target=...) call was made.
- Signal outbound logs for the incident window had no matching send row for the generated answer.
- The user did not receive the answer in Signal, even though unrelated Signal messages before/after were delivered normally.
This made the agent appear silent/unresponsive on Signal while the answer was present on the wrong/internal surface.
Redacted reproduction shape
This has not yet been reduced to a minimal unit test, but the live failure shape was:
- Start from a Signal direct-session inbound user turn.
- Have the turn processed or resumed through a Codex/vscode/internal runner context during ongoing background/rollout work.
- Let the assistant return a normal final response without an explicit message tool send.
- Observe that the final text is present in the internal/Codex transcript but no Signal outbound delivery is created for that text.
No private phone numbers, session UUIDs, raw transcript paths, or user message contents are included here.
Impact
Severity: high for affected sessions.
Consequences:
- User-visible Signal replies can be silently missed.
- Status updates and task answers can appear only in an internal/web/Codex surface.
- The workaround requires agents to explicitly call message(channel="signal", target=...) for user-facing replies from internal/event/Codex contexts, which should not be necessary for normal final responses.
Related issues / PRs
This issue is narrower: Signal inbound -> Codex/vscode/internal runner -> final assistant answer not delivered back to Signal.
Suggested fix direction
Add or tighten a delivery invariant around final assistant responses:
- Capture the inbound turn's original channel, target, account, and thread at turn start.
- When producing the final assistant reply, deliver to that captured route unless the turn explicitly opts into another route.
- Add regression coverage for: Signal inbound turn processed through a Codex/vscode/internal runner creates a Signal outbound send record for the final assistant text.
- Keep explicit message tool sends as intentional side-effect sends, but do not require them for ordinary final replies.
Version / environment
Observed on OpenClaw 2026.5.12 in a Signal direct-session workflow with Codex/OpenAI runner involvement.
Bug type
Behavior bug (incorrect routing / silent non-delivery)
Summary
A Signal direct-session user turn can be processed by a Codex/vscode/internal runner surface and produce the correct final assistant answer, but that final answer is not delivered back to the original Signal recipient unless the assistant explicitly calls the message tool.
This is a wrong-surface/silent-drop variant of the routing bugs tracked around async/internal followups. The answer exists, but the user never receives it in Signal.
Expected behavior
If an inbound turn originated from Signal, the normal final assistant response should be delivered back to that Signal channel/target, even when the active runner/surface is Codex, vscode, webchat, an inter-session event, or another internal execution context.
The delivery invariant should be tied to the original inbound channel/target for the turn, not whichever UI/runner surface happens to own the model execution.
Actual behavior
In the observed incident:
This made the agent appear silent/unresponsive on Signal while the answer was present on the wrong/internal surface.
Redacted reproduction shape
This has not yet been reduced to a minimal unit test, but the live failure shape was:
No private phone numbers, session UUIDs, raw transcript paths, or user message contents are included here.
Impact
Severity: high for affected sessions.
Consequences:
Related issues / PRs
This issue is narrower: Signal inbound -> Codex/vscode/internal runner -> final assistant answer not delivered back to Signal.
Suggested fix direction
Add or tighten a delivery invariant around final assistant responses:
Version / environment
Observed on OpenClaw 2026.5.12 in a Signal direct-session workflow with Codex/OpenAI runner involvement.