Skip to content

feat(auto-reply): persist ambient room events as transcript rows#99306

Merged
obviyus merged 1 commit into
mainfrom
codex/persist-ambient-rows
Jul 3, 2026
Merged

feat(auto-reply): persist ambient room events as transcript rows#99306
obviyus merged 1 commit into
mainfrom
codex/persist-ambient-rows

Conversation

@obviyus

@obviyus obviyus commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #99257. In ambient group mode (room_event turns) the agent evaluates every unmentioned message but is forced to forget it: get-reply-run.ts suppressed all room-event persistence, so group knowledge lived only in the bounded per-turn chat window (default 50 messages, rebuilt every turn in the uncached prompt tail). Messages older than the window were permanently invisible, compaction could not preserve ambient chat (nothing was persisted to summarize), and every turn re-paid the full window in fresh tokens.

Why This Change Was Made

The session transcript becomes the durable group chat log:

  • Bare attributed rows: each observed room event persists exactly one user-role transcript row in the same #id sender: body shape as the Current event display line (byte-identical). No metadata prefix, no window snapshot, no assistant row when the turn stays silent. Coalesced room events persist one row with each observed message as its own attributed line.
  • Watermark dedupe (the core invariant): a per-chat ambient watermark (SessionEntry.ambientTranscriptWatermarks, core-owned in src/config/sessions/ambient-transcript-watermark.ts) advances only after the row durably persists (onMessagePersisted hook on the user-turn transcript recorder), monotonically (timestamp-first, message-id tiebreak). Every prompt-facing consumer of the raw group history — the group-history entries, the cache-derived chat window (includeNode hook), room-event InboundHistory (no raw fallback; undefined when empty), and the recovered-thread paths — excludes everything at or before the watermark, so the per-turn window shrinks to the un-persisted gap (normally empty; covers races, coalesced bursts, and pre-feature history). The one intentional exemption is explicit reply targets (a quoted message stays visible even if transcript-owned, so the model never sees a reply to invisible text). All 14 raw-window consumer sites were enumerated as filtered-or-exempt during review.
  • Cutover, no knob: this is ambient mode's behavior; mention-only mode is untouched (the persist hook is wired only for room events). The room-event user-suppression special-casing is deleted rather than branched around; silent turns still suppress transcript-only assistant rows.
  • Channel-agnostic seam: core owns the watermark; the channel reads it via the documented plugin-sdk/session-store-runtime barrel (narrow channel hot-path helpers).

Net effect: append-only rows mean each group message costs its tokens once and is prompt-cache-hit on every later turn; compaction natively summarizes old ambient chat, so the agent retains the gist of messages far beyond any window.

User Impact

Ambient-mode deployments get durable full-chat awareness: the agent remembers group conversation across turns, restarts, and compaction, with strictly better cache economics than widening historyLimit. Reply gating is unchanged — the default-silent room-event contract (#99144) and the single-canonical-history payload shape (#99256) are preserved and test-pinned.

Evidence

  • Row shape, silent-turn assistant suppression, and watermark advance pinned in src/auto-reply/reply/get-reply-run.media-only.test.ts; dedupe boundary (persisted rows absent from the window, only the gap remains) in extensions/telegram/src/bot-message-context.prompt-context.test.ts.
  • Two review rounds (fresh branch autoreview) each caught a raw-window consumer bypassing the watermark — the live cache-derived group path and room-event InboundHistory + recovered threads. Each fix carries a regression test confirmed to fail without it (assertions on the final assembled prompt text, so future fallback paths also fail).
  • Consecutive user rows proven through embedded replay (src/agents/embedded-agent-runner/replay-history.test.ts), CLI session reseed (src/agents/cli-runner/session-history.test.ts), and strip-inbound-meta pass-through.
  • node scripts/run-vitest.mjs across all touched test files plus the affected-format sweep; pnpm tsgo, pnpm check:test-types, scoped oxlint on every touched file, pnpm prompt:snapshots:check — all green.
  • node scripts/run-vitest.mjs test/extension-test-boundary.test.ts src/scripts/test-projects.test.ts — green.
  • Blacksmith Testbox check:changed green on the final HEAD (exit 0) and on the two prior review-round HEADs.
  • Review posture: two fresh autoreview rounds each surfaced a watermark-bypass leak (fixed above, fail-confirmed regressions). A third full pass was skipped by maintainer decision after the reviewer process hung; the closing delta (InboundHistory + recovered-thread filtering) was instead manually verified against the enumeration.

@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram agents Agent runtime and tooling size: XL maintainer Maintainer-authored PR labels Jul 3, 2026
Persist room-event observations as durable bare user transcript rows and carry an ambient transcript watermark through session state so Telegram chat windows only include the unpersisted gap.

Fixes #99257
@obviyus
obviyus force-pushed the codex/persist-ambient-rows branch from 11cb4f2 to f6817fd Compare July 3, 2026 02:01
@obviyus
obviyus merged commit 3ad465d into main Jul 3, 2026
42 checks passed
@obviyus
obviyus deleted the codex/persist-ambient-rows branch July 3, 2026 02:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: telegram Channel integration: telegram maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist observed room events as bare transcript rows for durable ambient group awareness

1 participant