Skip to content

fix: capture text from intermediate tool_use iterations#989

Open
letzdoo-js wants to merge 1 commit intoRightNow-AI:mainfrom
letzdoo-js:fix/accumulated-text-response
Open

fix: capture text from intermediate tool_use iterations#989
letzdoo-js wants to merge 1 commit intoRightNow-AI:mainfrom
letzdoo-js:fix/accumulated-text-response

Conversation

@letzdoo-js
Copy link
Copy Markdown

Summary

Fix lost text responses when LLM produces text alongside tool_use blocks in the agent loop.

When an agent responds to a user AND calls tools (e.g., memory_store) in the same turn, the text is produced in an intermediate ToolUse iteration. If the final EndTurn iteration returns empty text, the empty-response guard activates and replaces the actual response with "[Task completed — the agent executed tools but did not produce a text summary.]"

This is a common pattern with Claude when agents are instructed to chat with users and persist state in the same conversation turn.

Changes

  • Added accumulated_text buffer in agent_loop.rs that captures text content from ToolUse iterations
  • Modified the EndTurn empty-text guard to use accumulated_text as fallback before triggering the guard
  • Applied to both sync and streaming agent loop paths

Testing

  • cargo clippy --workspace --all-targets -- -D warnings passes
  • cargo test --workspace passes
  • Live integration tested — Telegram-connected coaching agent that does memory_recall → text response → memory_store. Before: text lost. After: text captured
    correctly.

Security

  • No new unsafe code
  • No secrets or API keys in diff
  • User input validated at boundaries

When an LLM produces text alongside tool_use blocks (e.g., a chat
message followed by memory_store calls), the text was lost if the
final EndTurn iteration returned empty text. The empty-response guard
would activate and return "[Task completed — the agent executed tools
but did not produce a text summary.]" even though the agent DID
produce text in an earlier iteration.

This is a common pattern when agents are instructed to respond to
users AND persist state via memory_store in the same turn.

Fix: accumulate text content from all ToolUse iterations. When the
final EndTurn has empty text, use accumulated text as fallback before
triggering the empty-response guard.

Applied to both sync and streaming agent loop paths.
lc-soft pushed a commit to lc-soft/openfang that referenced this pull request Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants