Affected component
runtime/daemon
Severity
S2 - degraded behavior
Current behavior
The chat UI intermittently renders standalone tool cards labeled "unknown" with a spinner that never resolves.
Root cause: the gateway uses one shared broadcast::Sender<serde_json::Value> (event_tx, crates/zeroclaw-gateway/src/lib.rs:906) as a firehose. Both the monitoring SSE endpoint /api/events (sse.rs:72) and the chat WebSocket (ws.rs:513) subscribe to it; publishers include the observability BroadcastObserver (lib.rs:1333) and the log hook (lib.rs:1343).
BroadcastObserver emits a telemetry frame that reuses the chat protocol's tool_call type string but with a different shape (sse.rs:162-173):
{"duration_ms":10611,"success":true,"timestamp":"2026-06-03T09:00:54.513459643+00:00","tool":"file_write","type":"tool_call"}
The chat WS forwards the broadcast firehose nearly unfiltered (ws.rs:635-639), so this reaches the chat frontend. The frontend tool_call handler keys on name — absent here (the field is tool) → falls back to "unknown" — and there is no output, so the card never resolves. The chat's real tool frames ({"type":"tool_call","id","name","args"}, ws.rs:1010) flow out-of-band over a per-turn channel, so the collision is purely incidental coupling via the shared bus.
Expected behavior
The chat WebSocket should not carry unexpected (observability/telemetry) events; or the frontend should handle such events gracefully without rendering meaningless cards. In other words: either isolate the channel/namespace at the source so monitoring events never flow onto the chat socket, or have the frontend gracefully ignore tool_call frames that do not match the chat tool-frame shape (missing name/output) instead of producing a never-resolving "unknown" card.
Steps to reproduce
# 1. Run the gateway and open the web chat against an agent.
# 2. Send a message that triggers a tool the agent executes (e.g. file_write).
# 3. The agent's tool execution emits an observability ToolCall event onto event_tx.
# 4. Observe a standalone "unknown" tool card (wrench icon, spinner) appear in
# the chat that never resolves — separate from the real tool card.
Impact
Affected users: anyone using the web chat UI while tools execute.
Frequency: intermittent — whenever an observability tool_call event is broadcast during a chat session.
Consequence: confusing, never-resolving "unknown" cards clutter the transcript; cosmetic but erodes trust in the tool-activity view.
Logs / stack traces
Offending broadcast frame received by the chat WS client:
{"duration_ms":10611,"success":true,"timestamp":"2026-06-03T09:00:54.513459643+00:00","tool":"file_write","type":"tool_call"}
ZeroClaw version
commit 40be773
Rust version
rustc 1.95.0 (59807616e 2026-04-14)
Operating system
Linux 7.0.10-1-MANJARO x86_64 (Manjaro)
Regression?
Unknown
Pre-flight checks
Affected component
runtime/daemon
Severity
S2 - degraded behavior
Current behavior
The chat UI intermittently renders standalone tool cards labeled "unknown" with a spinner that never resolves.
Root cause: the gateway uses one shared
broadcast::Sender<serde_json::Value>(event_tx,crates/zeroclaw-gateway/src/lib.rs:906) as a firehose. Both the monitoring SSE endpoint/api/events(sse.rs:72) and the chat WebSocket (ws.rs:513) subscribe to it; publishers include the observabilityBroadcastObserver(lib.rs:1333) and the log hook (lib.rs:1343).BroadcastObserveremits a telemetry frame that reuses the chat protocol'stool_calltype string but with a different shape (sse.rs:162-173):{"duration_ms":10611,"success":true,"timestamp":"2026-06-03T09:00:54.513459643+00:00","tool":"file_write","type":"tool_call"}The chat WS forwards the broadcast firehose nearly unfiltered (
ws.rs:635-639), so this reaches the chat frontend. The frontendtool_callhandler keys onname— absent here (the field istool) → falls back to"unknown"— and there is nooutput, so the card never resolves. The chat's real tool frames ({"type":"tool_call","id","name","args"},ws.rs:1010) flow out-of-band over a per-turn channel, so the collision is purely incidental coupling via the shared bus.Expected behavior
The chat WebSocket should not carry unexpected (observability/telemetry) events; or the frontend should handle such events gracefully without rendering meaningless cards. In other words: either isolate the channel/namespace at the source so monitoring events never flow onto the chat socket, or have the frontend gracefully ignore
tool_callframes that do not match the chat tool-frame shape (missingname/output) instead of producing a never-resolving "unknown" card.Steps to reproduce
Impact
Affected users: anyone using the web chat UI while tools execute.
Frequency: intermittent — whenever an observability
tool_callevent is broadcast during a chat session.Consequence: confusing, never-resolving "unknown" cards clutter the transcript; cosmetic but erodes trust in the tool-activity view.
Logs / stack traces
Offending broadcast frame received by the chat WS client:
ZeroClaw version
commit 40be773
Rust version
rustc 1.95.0 (59807616e 2026-04-14)
Operating system
Linux 7.0.10-1-MANJARO x86_64 (Manjaro)
Regression?
Unknown
Pre-flight checks