Skip to content

fix(agent): deliver skills-like fallback replies when streaming - #10025

Merged
Soulter merged 2 commits into
AstrBotDevs:masterfrom
camera-2018:codex/fix-skills-like-streaming-reply
Sep 10, 2026
Merged

fix(agent): deliver skills-like fallback replies when streaming#10025
Soulter merged 2 commits into
AstrBotDevs:masterfrom
camera-2018:codex/fix-skills-like-streaming-reply

Conversation

@camera-2018

@camera-2018 camera-2018 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #10024

Motivation

With skills_like and streaming enabled, a tool-schema re-query can return a plain assistant reply instead of another tool call. The re-query uses non-streaming text_chat(), but this fallback only emits llm_result. The streaming bridge consumes streaming_delta, so the final reply is saved to history without reaching the user.

Modifications

  • In the no-tool re-query fallback only, emit the reply as streaming_delta when streaming is enabled, while retaining llm_result for non-streaming and stream-to-general consumers.
  • Append the new streaming events after the existing _complete_with_assistant_response() call, so they use the post-hook reply. Do not move the existing llm_result emissions or hook invocation.
  • Preserve reasoning as a separate chain so the bridge's reasoning visibility setting still applies.
  • Leave the generic stream bridge unchanged: forwarding every llm_result there would duplicate ordinary streamed replies.

No new settings, dependencies, platform-specific changes, or changes to cron notification policy.

Scope: only the missing streaming events in #10024. The existing non-streaming/stream-to-general llm_result-before-hook behavior is preserved. The separate hook-ordering issue #9788 is left to #9789 / #9835; this PR no longer changes that ordering. The production diff only adds 20 lines in the fallback branch.

  • This is NOT a breaking change.

Verification Steps and Test Results

Based on upstream master at 6fb50cae9.

Added regressions exercise the real ToolLoopAgentRunner, its schema re-query, and run_agent() with a deterministic fake provider/event. Coverage includes:

  • Plain completion_text and result_chain fallback replies.
  • Streaming with reasoning hidden/shown, non-streaming, and stream-to-general delivery.
  • Exactly-once final reply and intermediate text delivery.
  • Original complete-result events remaining before hooks, and only the newly added streaming deltas being emitted after hooks.
  • Retained complete-result events and final history content.
  • Ordinary streaming replies remaining single-delivery.
  • Existing successful re-query/tool execution coverage extended to streaming mode.

Before the fix, the new regression matrix fails (including missing final replies on the streaming cases); the ordinary streaming control passes. After the fix:

python -m pytest tests/test_tool_loop_agent_runner.py tests/test_astr_agent_run_util.py \
  tests/unit/test_astr_main_agent.py tests/unit/test_astr_agent_tool_exec.py \
  tests/unit/test_agent_runner_config.py tests/agent -q

317 passed, 1 warning

The warning is the existing Python audioop deprecation warning.

ruff format .       # Ruff 0.15.22: 504 files left unchanged
ruff check .        # All checks passed
git diff --check    # clean

Tests are local and deterministic; no real provider calls or platform messages were sent, and the production deployment was not modified. This is not a live Feishu end-to-end test.

Checklist

  • Changes are tested, with verification commands and results above.
  • No new dependencies are introduced.
  • No malicious code is introduced.

Summary by Sourcery

Ensure assistant replies produced by skills-like tool-schema re-queries reach streaming consumers without duplication.

Bug Fixes:

  • Deliver fallback assistant replies from skills-like streaming re-queries to users exactly once.
  • Preserve reasoning visibility and ensure agent-done hooks run before fallback stream content is emitted.

Enhancements:

  • Extend regression coverage across streaming, reasoning, result-chain, and stream-to-general delivery paths while confirming ordinary streaming replies are not duplicated.

Tests:

  • Add deterministic integration-style coverage for the real tool-loop runner, streaming bridge, hook ordering, response persistence, and final history content.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is tightly scoped, aligns with the stated streaming bridge semantics, and is covered by targeted regression tests that exercise the real runner/bridge behavior.

Pull request overview

This PR fixes a streaming delivery gap in the skills_like tool-schema re-query fallback path: when the re-query returns a plain assistant reply (no tool calls), the final answer previously only emitted llm_result and could be persisted to history without being delivered to streaming consumers.

Changes:

  • Emit the skills_like no-tool re-query fallback reply as streaming_delta (when streaming is enabled) while still emitting llm_result for non-streaming / stream-to-general consumers.
  • Ensure _complete_with_assistant_response() (and thus agent-done hooks) runs before emitting the fallback content.
  • Add regression tests covering streaming vs non-streaming, reasoning visibility, stream-to-general behavior, exactly-once delivery, and “normal streaming reply not duplicated” controls.
File summaries
File Description
astrbot/core/agent/runners/tool_loop_agent_runner.py Moves fallback completion before emission and emits fallback content via streaming_delta in streaming mode (plus llm_result for non-streaming consumers).
tests/test_tool_loop_agent_runner.py Adds/extends tests to validate fallback delivery and hook ordering across streaming modes and to ensure ordinary streaming replies are not duplicated.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Soulter
Soulter merged commit 0f445f5 into AstrBotDevs:master Sep 10, 2026
23 checks passed
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.

[Bug] 开启 skills_like 和流式回复后,工具调用完成但未发送最终回答

3 participants