Skip to content

Treat ambient group chatter as room events#81317

Merged
steipete merged 21 commits into
mainfrom
codex/room-event-turns
May 15, 2026
Merged

Treat ambient group chatter as room events#81317
steipete merged 21 commits into
mainfrom
codex/room-event-turns

Conversation

@obviyus
Copy link
Copy Markdown
Contributor

@obviyus obviyus commented May 13, 2026

Summary

  • Add room-event turn semantics so ambient group chatter runs as context, not a fake user request.
  • Route Telegram always-on non-trigger group messages through message-tool-only invisible room events.
  • Keep room events visible in context maps and group history without replaying private no-tool assistant text.
  • Keep room events fully quiet across Telegram ack/status reactions and reasoning drafts unless the agent calls the message tool.
  • Keep the inbound turn-kind type in a dependency-free leaf so architecture checks stay acyclic.

Verification

  • pnpm test extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/bot-message-context.reactions.test.ts extensions/telegram/src/bot-message-context.require-mention.test.ts src/channels/turn/context.test.ts
  • pnpm check:architecture
  • pnpm check:changed

Real behavior proof

  • Behavior or issue addressed: Ambient always-on Telegram group messages should run as room events, stay quiet by default, preserve room context, and speak only through message(action=send).
  • Real environment tested: Real Telegram bot-to-bot group harness with a temp OpenClaw gateway running this PR worktree.
  • Exact steps or command run after this patch: Ran the local Telegram E2E harness against the PR gateway for tagged control, ambient no-leak, ambient message-tool send, and room-context carry-forward scenarios.
  • Evidence after fix: Copied live output from the Telegram E2E run: tagged control sent message 7787 and SUT replied 7788 with OPENCLAW_E2E_OK; ambient no-leak sent 7789 and observed no SUT reply with provider requests 1; ambient message-tool send sent 7790 and SUT replied 7791 with OPENCLAW_E2E_TOOL_SEND_81317; room-context carry-forward sent ambient 7792, tagged request 7793, and SUT replied 7794 with OPENCLAW_E2E_CONTEXT_SEEN_81317.
  • Observed result after fix: Ambient room events stayed invisible unless the mock provider explicitly called the message tool, and a later direct group request saw the prior ambient room event as context.
  • What was not tested: No additional gaps.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: telegram Channel integration: telegram agents Agent runtime and tooling size: M maintainer Maintainer-authored PR labels May 13, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 13, 2026

Codex review: needs maintainer review before merge.

Summary
The PR adds opt-in messages.groupChat.ambientTurns: "room_event" handling, propagates inbound turn kind through Telegram, reply, gateway, tool, and protocol paths, and updates docs, tests, and generated protocol artifacts.

Reproducibility: not applicable. as a current-main bug reproduction: this PR adds a new opt-in room-event mode, and current main does not contain the ambientTurns or room_event surfaces. The contributor did provide after-fix live Telegram proof for the new behavior.

Real behavior proof
Sufficient (live_output): The PR includes copied after-fix live Telegram bot-to-bot output showing quiet ambient room events, explicit message-tool visible send, and context carry-forward.

Next step before merge
Protected maintainer label plus new feature/config/protocol semantics require human approval; there is no narrow ClawSweeper repair finding to queue.

Security
Cleared: The diff touches Telegram turn semantics, gateway/tool context, generated protocol artifacts, config, docs, and tests without adding dependencies, workflows, permissions, secret handling, or external code execution paths.

Review details

Best possible solution:

Land the room-event model only after maintainer approval confirms the new config and protocol surface, preserving the compatibility default and strict message-tool-only visible delivery for room events.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a current-main bug reproduction: this PR adds a new opt-in room-event mode, and current main does not contain the ambientTurns or room_event surfaces. The contributor did provide after-fix live Telegram proof for the new behavior.

Is this the best way to solve the issue?

Unclear until maintainer product approval because the PR adds new user-facing config plus protocol and tool-surface propagation. From code review, the approach is cohesive and I found no narrow blocking correctness defect.

Acceptance criteria:

  • node scripts/run-vitest.mjs extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/bot-message-context.reactions.test.ts extensions/telegram/src/bot-message-context.require-mention.test.ts src/channels/turn/context.test.ts
  • pnpm check:architecture
  • pnpm check:changed
  • Real Telegram bot-to-bot proof for tagged control, ambient no-leak, message-tool send, and context carry-forward

What I checked:

  • Live protected PR state: Public GitHub API shows this PR is open, unmerged, based on current main, and labeled maintainer, proof: sufficient, and mantis: telegram-visible-proof; protected-label cleanup close is not allowed. (b8c5a7989caf)
  • Current main baseline: Current main has no ambientTurns, room_event, or InboundTurnKind implementation in the searched Telegram, source, docs, app, script, or changelog paths. (0b7ff665f664)
  • Configuration surface: The PR adds messages.groupChat.ambientTurns as an optional enum with user_request as the compatibility default and room_event as the new behavior. (src/config/types.messages.ts:11, b8c5a7989caf)
  • Telegram classification: The PR classifies only configured unmentioned group turns as room_event, excluding mentions, control commands, aborts, and native commands. (extensions/telegram/src/bot-message-context.session.ts:433, b8c5a7989caf)
  • Quiet delivery enforcement: Room events are dispatched with sourceReplyDeliveryMode: "message_tool_only", queued delivery correlation, suppressed typing, and no progress callbacks while source delivery is suppressed. (extensions/telegram/src/bot-message-dispatch.ts:1517, b8c5a7989caf)
  • Gateway protocol propagation: The gateway message-action schema adds optional inboundTurnKind as an additive enum field. (src/gateway/protocol/schema/agent.ts:82, b8c5a7989caf)

Likely related people:

  • @steipete: Current-main blame/log on the central Telegram dispatch/context paths points to Peter Steinberger, and the PR commit list includes multiple room-event gating, delivery-correlation, queue, and tool-context follow-ups by this person. (role: recent area contributor and PR follow-up owner; confidence: high; commits: 1ba75463a520, 599a929a366f, d5d448f43b85; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/bot-message-context.ts, extensions/telegram/src/bot-message-context.session.ts)

Remaining risk / open question:

  • This is a large cross-cutting feature/config/protocol change and still needs explicit maintainer product approval plus the normal broad merge checks.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 0b7ff665f664.

@obviyus
Copy link
Copy Markdown
Contributor Author

obviyus commented May 13, 2026

Simple behavior summary:

requireMention: false still means OpenClaw runs on every group message, so the agent keeps full room context.

What changes is the shape of the turn. Ambient group chatter is now a room event, not a fake direct user request.

Example:

Alice: lunch at 2?
Bob: works
You: hey claw summarise the plan

All of those messages can be observed as room events. The model still sees them, so on the last one it can decide, "this is clearly for me," and reply visibly by calling message(action=send).

The important difference: normal final assistant text no longer automatically leaks into the group for ambient chatter. The agent can still reply without an explicit @tag, but visible speech is now a deliberate message-tool action instead of the default output path.

@clawsweeper clawsweeper Bot added the mantis: telegram-visible-proof Mantis should capture Telegram visible proof. label May 13, 2026
@obviyus obviyus self-assigned this May 13, 2026
@obviyus
Copy link
Copy Markdown
Contributor Author

obviyus commented May 13, 2026

Telegram E2E proof

Ran against codex/room-event-turns (cd1389becfb44291da2bdf48e23cfc82c4006b5d) with the real Telegram bot-to-bot harness and temp OpenClaw gateway from this worktree.

  • Tagged control:

    • Command: node /Users/obviyus/.codex/skills/custom/telegram-e2e-bot-to-bot/scripts/run-mock-sut-e2e.mjs --gateway-port 19989 --mock-port 19992 --text '@{sut} Please answer with OPENCLAW_E2E_OK only.' --expect OPENCLAW_E2E_OK --timeout-ms 120000 --output /tmp/openclaw-pr81317-mention-ok.json
    • Sent 7787; SUT replied 7788 with OPENCLAW_E2E_OK; provider requests: 1.
  • Ambient no-leak check:

    • Command: node /Users/obviyus/.codex/skills/custom/telegram-e2e-bot-to-bot/scripts/run-mock-sut-e2e.mjs --gateway-port 19999 --mock-port 20002 --text 'ambient final text leak check OPENCLAW_E2E_OK' --expect OPENCLAW_E2E_OK --timeout-ms 25000 --output /tmp/openclaw-pr81317-ambient-no-leak.json
    • Sent 7789; no SUT reply observed; provider requests: 1.
    • Verified provider input was the room-event path: final replies private, visible output requires message(action=send).
  • Ambient message-tool send:

    • Command: local one-off node <<'NODE' ... runner with a mock Responses server that returns message({ action: "send", message: "OPENCLAW_E2E_TOOL_SEND_81317" }).
    • Sent 7790; SUT replied 7791 with OPENCLAW_E2E_TOOL_SEND_81317; provider requests: 1.
    • Verified the first provider request had the room-event prompt and was not a mention.
  • Room context carry-forward:

    • Command: local one-off node <<'NODE' ... runner that sent ambient ROOMCTX_SEED_81317_LUNCH_AT_2, then sent a tagged summary request.
    • Ambient sent 7792; visible ambient replies: 0.
    • Tagged request sent 7793; SUT replied 7794 with OPENCLAW_E2E_CONTEXT_SEEN_81317.
    • Provider requests: 2; verified the second provider request contained the ambient room-event seed.

@obviyus
Copy link
Copy Markdown
Contributor Author

obviyus commented May 13, 2026

Addressed review findings in 8b593668cd:

  • room events no longer create Telegram reasoning draft streams
  • room events no longer drive ack/status/tool/compaction reactions
  • PR body now includes redacted Telegram E2E proof

Verification:

  • pnpm test extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/bot-message-context.reactions.test.ts extensions/telegram/src/bot-message-context.require-mention.test.ts
  • pnpm check:changed

@clawsweeper re-review

@obviyus
Copy link
Copy Markdown
Contributor Author

obviyus commented May 13, 2026

Follow-up pushed in bc6a3063c0:

  • moved InboundTurnKind to a dependency-free leaf type
  • fixed the madge architecture cycle reported by CI

Additional verification:

  • pnpm check:architecture
  • pnpm test extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/bot-message-context.reactions.test.ts extensions/telegram/src/bot-message-context.require-mention.test.ts src/channels/turn/context.test.ts
  • pnpm check:changed

@obviyus
Copy link
Copy Markdown
Contributor Author

obviyus commented May 13, 2026

Follow-up pushed in 9cd3c39886:

  • made room-event turn input an explicit [OpenClaw turn] envelope
  • put kind: room_event and visible_reply_contract: message_tool_only before room context
  • rendered the current event with message id + sender inline, so the LLM sees the active room event as a transcript line instead of a bare body

Additional verification:

  • pnpm test src/auto-reply/reply/prompt-prelude.test.ts src/auto-reply/reply/get-reply-run.media-only.test.ts
  • pnpm check:changed
  • deployed to WSL2 Docker bot; gateway healthy, Codex bundled, and running image contains visible_reply_contract

@clawsweeper re-review

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 13, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 13, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@obviyus obviyus requested a review from a team as a code owner May 13, 2026 16:45
@obviyus obviyus force-pushed the codex/room-event-turns branch from d11cb3c to 545b2b1 Compare May 14, 2026 02:02
@icophy
Copy link
Copy Markdown

icophy commented May 14, 2026

Running OpenClaw on Feishu with group chats, so this change is directly relevant to my setup.

The current behavior — every ambient group message triggering a full agent turn — creates a few practical problems I've been working around:

  1. Context pollution: When the group is active, the agent's context fills with unrelated chatter before the actual request arrives. By the time someone tags the bot, the relevant context is diluted.
  2. Reaction noise: Feishu shows typing indicators and read receipts. Every ambient message triggering a turn means the bot appears to be "thinking" constantly, which confuses group members.
  3. Cron interference: I run scheduled tasks (cron jobs) that fire during active group hours. The ambient message turns were occasionally interleaving with cron-triggered turns in ways that were hard to debug.

The room-event model solves all three cleanly. Ambient messages become context without triggering visible agent behavior — which is exactly the right semantic.

One question about the implementation: does the room-event context have a size limit or TTL? In a busy group, the accumulated room context before a tagged request could get large. I'm curious whether there's a mechanism to bound it (e.g., last N messages, or last M minutes) or whether that's left to the model's context window management.


Context: Running OpenClaw as a persistent agent on a Feishu group, with cron-scheduled tasks and always-on group monitoring.

@obviyus obviyus force-pushed the codex/room-event-turns branch from 545b2b1 to 14cd004 Compare May 14, 2026 02:20
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 14, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@obviyus obviyus force-pushed the codex/room-event-turns branch from 14cd004 to 9a05098 Compare May 14, 2026 02:45
@clawsweeper clawsweeper Bot removed proof: sufficient ClawSweeper judged the real behavior proof convincing. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. labels May 14, 2026
@obviyus obviyus force-pushed the codex/room-event-turns branch from 9a05098 to 8334e8d Compare May 14, 2026 05:49
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. labels May 14, 2026
@obviyus obviyus force-pushed the codex/room-event-turns branch from faef55d to 4f4a874 Compare May 15, 2026 02:20
@steipete steipete force-pushed the codex/room-event-turns branch 2 times, most recently from 482e182 to b8c5a79 Compare May 15, 2026 20:12
@steipete steipete force-pushed the codex/room-event-turns branch from b8c5a79 to b8f52e7 Compare May 15, 2026 20:47
@steipete steipete merged commit 903e246 into main May 15, 2026
25 checks passed
@steipete steipete deleted the codex/room-event-turns branch May 15, 2026 20:47
@steipete
Copy link
Copy Markdown
Contributor

Landed via rebase merge onto main.

  • Source head: b8f52e7
  • Merge commit: 903e246
  • Proof: codex-review clean; git diff --check origin/main; scoped oxfmt check; pnpm build:plugin-sdk:strict-smoke; focused room-event/Telegram/gateway/outbound test set passed before final rebase.
  • CI: skipped waiting for remaining queued checks per maintainer request; previously failing check-strict-smoke passed on GitHub after the fix.

Thanks @obviyus!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui channel: telegram Channel integration: telegram docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR mantis: telegram-visible-proof Mantis should capture Telegram visible proof. proof: sufficient ClawSweeper judged the real behavior proof convincing. scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants