openclaw - ✅(Solved) Fix [Bug]: Gateway file logs include full subagent announce/completion message bodies instead of metadata-only entries [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#62500Fetched 2026-04-08 03:03:28
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×1labeled ×1referenced ×1

When a spawned subagent finishes and OpenClaw emits the completion/announce event back into the parent session, the Gateway file log records the full user-facing rendered message body as info log lines.

This causes openclaw logs and the Gateway file log to fill up with chat-like content such as:

  • work summaries
  • progress updates
  • commit summaries
  • verification results

These are not operational logs in the normal sense. They are user-facing announce payloads and should not be dumped into the Gateway file log body verbatim.

The behavior appears tied to the subagent announce path, with log entries around:

  • runId=announce:v1:agent:writer:subagent:...

The problem is not that the subagent writes to the log directly. The issue appears to be that the runtime announce/completion event is logged as full text by the Gateway logger.

Root Cause

When a spawned subagent finishes and OpenClaw emits the completion/announce event back into the parent session, the Gateway file log records the full user-facing rendered message body as info log lines.

This causes openclaw logs and the Gateway file log to fill up with chat-like content such as:

  • work summaries
  • progress updates
  • commit summaries
  • verification results

These are not operational logs in the normal sense. They are user-facing announce payloads and should not be dumped into the Gateway file log body verbatim.

The behavior appears tied to the subagent announce path, with log entries around:

  • runId=announce:v1:agent:writer:subagent:...

The problem is not that the subagent writes to the log directly. The issue appears to be that the runtime announce/completion event is logged as full text by the Gateway logger.

Fix Action

Fixed

PR fix notes

PR #62536: fix(logging): route subagent announce output through subsystem logger

Description (problem / solution / changelog)

Summary

  • Problem: Gateway file logs record full subagent announce/completion assistant response bodies as info lines, polluting operational logs with chat content.
  • Why it matters: Logs become noisy and hard to debug; large multi-line summaries bloat file size; user-facing text mixed into system logs is misleading and a potential privacy concern.
  • What changed: Announce delivery output now routes through createSubsystemLogger("agents/announce") — metadata at info, full body at debug. Announce-related error/warning logging in subagent-announce.ts and subagent-announce-delivery.ts also moved from defaultRuntime to the subsystem logger.
  • What did NOT change (scope boundary): Normal (non-announce) agent delivery logging, channel delivery, session transcript writes, or any LLM behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #62500
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: deliverAgentCommandResult() in delivery.ts calls runtime.log(output) for announce run payloads. In the gateway process, runtime.log()console.log()enableConsoleCapture() intercepts all console.log calls and forwards them to the tslog root logger at info level via getLogger().info(formatted), which writes to the rolling date file.
  • Missing detection / guardrail: No distinction between announce-internal output and normal agent output in the delivery logging path. Announce runs use the same logPayload() / logNestedOutput() path as user-facing agent runs.
  • Contributing context (if known): The announce delivery files (subagent-announce.ts, subagent-announce-delivery.ts) had no subsystem logger at all — errors went through defaultRuntime.error() which also hits the console capture path.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/command/delivery.test.ts
  • Scenario the test should lock in: When inputProvenance.sourceTool === "subagent_announce", runtime.log() must NOT receive the full payload body; instead announceLog.info() receives metadata and announceLog.debug() receives the full body.
  • Why this is the smallest reliable guardrail: Tests the exact decision point in logPayload() without requiring a live gateway or real subagent completion.
  • Existing test that already covers this (if any): None — this gap is why the log pollution went undetected.
  • If no new test is added, why not: A new test is added.

User-visible / Behavior Changes

  • openclaw logs output no longer includes full subagent completion prose at default log level.
  • Announce metadata (session, runId, payload size) still appears at info.
  • Full announce body is available at debug level for troubleshooting.

Diagram (if applicable)

Before:
[subagent completes] → deliverAgentCommandResult → runtime.log(fullBody)
  → console.log(fullBody) → enableConsoleCapture → getLogger().info(fullBody)
  → openclaw-YYYY-MM-DD.log (info, no subsystem, full chat text)

After:
[subagent completes] → deliverAgentCommandResult → announceLog.info(metadata)
  → logToFile(fileLogger, "info", metadata)    ← clean operational log
  → announceLog.debug(fullBody)
  → logToFile(fileLogger, "debug", fullBody)   ← only at debug level

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22+ / pnpm workspace
  • Model/provider: Any
  • Integration/channel (if any): Any channel with subagent spawning

Steps

  1. Start a gateway with logging.level: debug or default info
  2. Spawn a subagent that produces a multi-line completion summary
  3. Let the subagent complete and announce back to the parent session
  4. Inspect gateway logs via openclaw logs --plain --local-time

Expected

  • Gateway file logs show only announce metadata (session, runId, chars) at info level
  • Full completion body appears only at debug level

Actual

  • Before this fix: full completion body appears at info level with no subsystem tag
  • After this fix: metadata-only at info, full body at debug

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios:
    • New unit test confirms announce payloads route through subsystem logger instead of runtime.log
    • All 14 existing announce-related tests pass (delivery + announce + announce-delivery)
    • pnpm check lint/format clean
  • Edge cases checked:
    • Non-announce agent runs still use the original runtime.log() path (unchanged)
    • opts.json mode still uses runtime.log(JSON.stringify(...)) (unchanged)
    • Nested non-announce runs still use logNestedOutput() (unchanged)
  • What you did not verify:
    • Full end-to-end gateway run with a real subagent completion (verified via code path analysis and unit test)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Announce errors previously written via defaultRuntime.error() now go through subsystem logger, which uses rawConsole instead of patched console.
    • Mitigation: Both paths write to stderr and file log at error level. The only difference is the subsystem logger adds a [agents/announce] tag, which is an improvement for filtering.

AI-assisted: Built with Claude. All changes reviewed and understood. 14/14 related tests passing.

Changed files

  • src/agents/command/delivery.test.ts (modified, +88/-0)
  • src/agents/command/delivery.ts (modified, +16/-0)
  • src/agents/subagent-announce-delivery.ts (modified, +5/-3)
  • src/agents/subagent-announce.ts (modified, +19/-4)

Code Example

Example evidence from Gateway log:


2026-04-07T18:53:50.353+07:00 info gateway/ws {"subsystem":"gateway/ws"} ⇄ res ✓ agent.wait 579081ms conn=... id=...
2026-04-07T18:53:51.740+07:00 info - Changed:
  - Added shared phase D helpers in `tools/approval_common.py` to detect “published elsewhere but stale here” drift from:
    - paired manifest
    - approval-map published record
    - matching receipt by stem
  - Added repair helper to normalize stale pending manifests to `published` with proof metadata.
  ...
  ✅ commit `bbe13cb` — pushed to main
2026-04-07T18:53:52.071+07:00 info gateway/ws {"subsystem":"gateway/ws"} ⇄ res ✓ agent 64ms runId=announce:v1:agent:writer:subagent:... conn=... id=...


Another example:


2026-04-07T19:10:45.792+07:00 info Done.

What changed
- Found the false-success gap: both approval-card send paths were treating “payload built and printed” as if it meant “message delivered”.
- Added a delivery contract in `tools/approval_common.py`:
  - `make_delivery_pending_envelope(...)`
  - `verify_delivery_result(...)`
...
Commit
- `edaf79fd3348f52e731931e8958f36821f01691c`


Another example of parent-session user-facing update being logged:


2026-04-07T19:11:22.276+07:00 info เสร็จครบ AF แล้วครับ
...
✅ commit `edaf79f` — pushed to main


Related signal that seems tied to the same path:
- announce runs are visible in log metadata as:
  - `runId=announce:v1:agent:writer:subagent:...`

Observed behavior suggests the announce/completion path is being logged as full assistant text rather than metadata-only event logging.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When a spawned subagent finishes and OpenClaw emits the completion/announce event back into the parent session, the Gateway file log records the full user-facing rendered message body as info log lines.

This causes openclaw logs and the Gateway file log to fill up with chat-like content such as:

  • work summaries
  • progress updates
  • commit summaries
  • verification results

These are not operational logs in the normal sense. They are user-facing announce payloads and should not be dumped into the Gateway file log body verbatim.

The behavior appears tied to the subagent announce path, with log entries around:

  • runId=announce:v1:agent:writer:subagent:...

The problem is not that the subagent writes to the log directly. The issue appears to be that the runtime announce/completion event is logged as full text by the Gateway logger.

Steps to reproduce

  1. Start from a normal OpenClaw setup with Gateway running locally.
  2. In a chat/session, spawn a subagent that returns a multi-line result summary.
  3. Let the subagent complete successfully.
  4. Allow the parent session to receive and rewrite/deliver the completion update.
  5. Inspect Gateway logs using either:
    • openclaw logs --plain --local-time
    • or the underlying Gateway file log path shown by openclaw logs
  6. Observe that the full user-facing completion text is present in the Gateway log as info lines.

Expected behavior

Gateway file logs should record only metadata for announce/completion runs, for example:

  • run id
  • source session
  • target session
  • status
  • duration
  • payload size or char count
  • optional short preview, if intentionally allowed

They should not log the full rendered user-facing announce/completion body by default.

Actual behavior

Gateway logs include the entire user-facing completion/update message body, for example:

  • What changed ...
  • อัปเดตระหว่างทางครับ ...
  • Done. Commands run ...
  • เสร็จครบ A → F แล้วครับ ...

These appear as info log lines adjacent to announce-run metadata such as:

  • runId=announce:v1:agent:writer:subagent:...

This pollutes operational logs with chat/update prose and makes logs noisy, misleading, and much larger than necessary.

OpenClaw version

2026.4.5

Operating system

macOS 26.4

Install method

npm

Model

openai-codex/gpt-5.4

Provider / routing chain

openclaw->openai-codex/gpt-5.4

Additional provider/model setup details

Environment

  • OpenClaw version: 2026.4.5
  • Build: 3e72c03
  • OS: macos 26.4 (arm64)
  • Node: 22.22.2
  • Gateway mode: local
  • Gateway reachable via: ws://127.0.0.1:18789
  • Surface/channel in active reproduction: Telegram
  • Agent runtime observed: writer agent plus spawned subagents
  • Model mix observed during reproduction: gpt-5.4, gpt-5.4-mini

Logs, screenshots, and evidence

Example evidence from Gateway log:


2026-04-07T18:53:50.353+07:00 info gateway/ws {"subsystem":"gateway/ws"} ⇄ res ✓ agent.wait 579081ms conn=... id=...
2026-04-07T18:53:51.740+07:00 info - Changed:
  - Added shared phase D helpers in `tools/approval_common.py` to detect “published elsewhere but stale here” drift from:
    - paired manifest
    - approval-map published record
    - matching receipt by stem
  - Added repair helper to normalize stale pending manifests to `published` with proof metadata.
  ...
  ✅ commit `bbe13cb` — pushed to main
2026-04-07T18:53:52.071+07:00 info gateway/ws {"subsystem":"gateway/ws"} ⇄ res ✓ agent 64ms runId=announce:v1:agent:writer:subagent:... conn=... id=...


Another example:


2026-04-07T19:10:45.792+07:00 info Done.

What changed
- Found the false-success gap: both approval-card send paths were treating “payload built and printed” as if it meant “message delivered”.
- Added a delivery contract in `tools/approval_common.py`:
  - `make_delivery_pending_envelope(...)`
  - `verify_delivery_result(...)`
...
Commit
- `edaf79fd3348f52e731931e8958f36821f01691c`


Another example of parent-session user-facing update being logged:


2026-04-07T19:11:22.276+07:00 info เสร็จครบ A → F แล้วครับ
...
✅ commit `edaf79f` — pushed to main


Related signal that seems tied to the same path:
- announce runs are visible in log metadata as:
  - `runId=announce:v1:agent:writer:subagent:...`

Observed behavior suggests the announce/completion path is being logged as full assistant text rather than metadata-only event logging.

Impact and severity

Severity: Medium to High

Why this matters:

  1. Operational log pollution
    • Gateway logs become filled with user-facing prose rather than system/transport events.
  2. Reduced debuggability
    • Important real errors and transport/runtime diagnostics are harder to find.
  3. Misleading log semantics
    • Human-facing completion text is mixed into logs as if it were system log content.
  4. Log volume bloat
    • Large multi-line summaries significantly increase log size.
  5. Potential privacy or sensitivity concerns
    • User-facing summaries may contain more contextual detail than should appear in Gateway file logs by default.

Suggested fix:

  • For announce/completion runs, log metadata only by default.
  • Do not emit full rendered assistant or user-facing announce bodies into Gateway file logs.
  • If full body logging is ever needed, gate it behind an explicit debug or verbose option.

Additional information

No response

extent analysis

TL;DR

Modify the Gateway logger to log only metadata for announce/completion runs by default, excluding full user-facing message bodies.

Guidance

  • Identify the logging mechanism used by the Gateway for announce/completion events and adjust it to capture metadata such as run ID, source session, target session, status, duration, and payload size, without including the full user-facing message body.
  • Consider adding an optional debug or verbose logging feature to allow for full message body logging when explicitly enabled.
  • Review the logging configuration to ensure that user-facing messages are not being logged as info lines, which could be misleading and pollute operational logs.
  • Verify that the modified logging behavior correctly captures metadata without including unnecessary user-facing content.

Example

No specific code example is provided due to the lack of explicit logging mechanism details in the issue. However, the adjustment might involve modifying a logging function or configuration to filter out full message bodies from announce/completion events.

Notes

The suggested fix assumes that the logging mechanism can be adjusted to differentiate between metadata and user-facing content. The exact implementation details may vary depending on the underlying logging system and Gateway architecture.

Recommendation

Apply a workaround by modifying the logging configuration to exclude full user-facing message bodies from Gateway logs, as this directly addresses the issue of operational log pollution and improved debuggability.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Gateway file logs should record only metadata for announce/completion runs, for example:

  • run id
  • source session
  • target session
  • status
  • duration
  • payload size or char count
  • optional short preview, if intentionally allowed

They should not log the full rendered user-facing announce/completion body by default.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING