Skip to content

fix(agent_loop): cap accumulated_text + document streaming non-redelivery contract#3106

Merged
houko merged 2 commits into
mainfrom
followup/agent-loop-review
Apr 25, 2026
Merged

fix(agent_loop): cap accumulated_text + document streaming non-redelivery contract#3106
houko merged 2 commits into
mainfrom
followup/agent-loop-review

Conversation

@houko

@houko houko commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up review concerns from #3091 (already merged).

  • Document the streaming-already-emitted semantics of accumulated_text in the runtime agent loop so future readers understand it is not redelivered to the channel.
  • Cap accumulated_text growth at 64 KB to prevent unbounded memory growth during long tool-use chains, with a regression test.

Cherry-picks: f273085, a1fc59d

Test plan

  • Existing runtime tests still pass
  • New cap test exercises the 64 KB truncation path

houko added 2 commits April 25, 2026 18:50
…d semantics

A reviewer raised the concern that pushing intermediate tool_use text
into `accumulated_text` could cause a double display when the streaming
path falls back to it for an empty final EndTurn — first via the live
stream, then again as `final_response`.

Verification (grep on bridge.rs):
  * Streaming success arm (~bridge.rs:3032 `Ok(())`) calls only
    `record_delivery` + `send_lifecycle_reaction`. It does NOT invoke
    `send_response(buffered_text)`. The buffered fallback only fires on
    the `Err(stream_error)` adapter-failure arm — that is recovery, not
    a duplicate emit.
  * `signal_response_complete` is a phase-change ping, not a re-emit of
    response text.
  * `final_response` (which may carry the accumulated_text fallback) is
    consumed for session persistence, memory extraction, and hooks —
    never pushed back onto `stream_tx`.

Conclusion: the concern is a false positive against the current wiring.

This commit pins the contract in code so a future refactor of the
bridge cannot quietly introduce a double display: the comment explains
the post-stream-fallback semantics and flags the exact invariant that
must hold (stream success arm must NOT re-emit `final_response` unless
the empty-text fallback is suppressed).
…owth

`accumulated_text` is appended on every iteration that emits text alongside
tool_use blocks. Across long autonomous loops or retry storms this buffer
could grow to megabytes per active session, pinning heap until the loop
ends. Fix:

* Introduce `ACCUMULATED_TEXT_MAX_BYTES = 64 KiB` (≈10× a Slack message
  limit, comfortably above any realistic user-facing reply).
* New `push_accumulated_text` helper centralises the append: it preserves
  the existing buffered prefix when the cap is hit, seals the buffer with
  ASCII padding so subsequent calls short-circuit, and emits exactly one
  `warn!` on the transition (no log spam).
* Both the non-streaming and streaming agent loops now route their
  intermediate-text capture through the helper.

Tests: cover separator behaviour, exact-cap sealing, prefix preservation,
short-circuit after seal, and unchanged behaviour under the cap.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions github-actions Bot added ready-for-review PR is ready for maintainer review area/runtime Agent loop, LLM drivers, WASM sandbox labels Apr 25, 2026
@github-actions github-actions Bot added the size/M 50-249 lines changed label Apr 25, 2026
@houko
houko merged commit f9332a6 into main Apr 25, 2026
22 checks passed
@houko
houko deleted the followup/agent-loop-review branch April 25, 2026 12:03
@github-actions github-actions Bot removed the ready-for-review PR is ready for maintainer review label Apr 25, 2026
@houko houko mentioned this pull request Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/runtime Agent loop, LLM drivers, WASM sandbox size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant