agentscope-ai / agentscope-ai/QwenPaw
[Feature]: Suppress final text response after tool calls in interactive channels
- Lenguaje dominante
- Python
- Estrellas
- 34.9k
- Forks
- 3.1k
- Merge medio
- 1 d 15 h
- PR fusionados (30 d)
- 225
Descripción
# [Feature]: Support suppressing final text response after tool calls in interactive channels
## Summary
Add a channel-level configuration option to suppress the agent's final text response after tool execution completes. This would allow "silent" tool execution where only the tool's output is sent to the user, without the agent's conversational summary.
## Component(s) Affected
- [x] Core / Backend (app, agents, config, providers, utils, local_models)
- [ ] Console (frontend web UI)
- [x] Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.) — **Telegram, Console**
- [ ] Skills
- [ ] CLI
- [ ] Documentation (website)
- [ ] Tests
- [ ] CI/CD
- [ ] Scripts / Deploy
## Problem / Motivation
Currently, after any tool call completes, the ReAct agent loop sends the tool_result back to the LLM, which generates a final conversational response summarizing the result. This behaviour is hardcoded in `agentscope/_react_agent.py` and cannot be disabled per-channel.
**This blocks legitimate use cases:**
### 1. Voice Reply Pipelines (Primary Use Case)
Users building voice interaction flows (voice → transcribe → TTS → voice reply) receive:
- ✅ Audio file with spoken response
- ❌ Unwanted text caption duplicating the audio content
The text follow-up clutters chat interfaces and cannot be suppressed via prompt engineering ("don't write text, only use the tool") — LLMs consistently ignore this constraint.
### 2. Clean Automated Notifications
Similar to the cron job use case in [#2452](https://github.com/agentscope-ai/QwenPaw/issues/2452), but for **interactive** channels:
- Users bridging QwenPaw to external systems want clean data output
- Conversational filler ("I've completed the search for you...") consumes tokens and clutters logs
- Prompt engineering is unreliable across models
### 3. Multi-Modal Workflows
When a tool produces rich output (image, audio, document), the text summary is often redundant:
- Image generation → user sees the image, doesn't need "Here's your image"
- File creation → user receives the file, doesn't need "I've created the file"
## Related Issues
- **#2452** — [Feature]: Support suppressing Agent's conversational response after script execution in Cron jobs (open, since 2026-03-28)
- This request **generalizes [#2452](https://github.com/agentscope-ai/QwenPaw/issues/2452)** beyond cron jobs to interactive channels
- Same underlying problem: no way to bypass the final LLM response generation step
## Proposed Solution
### 1. Add Channel Configuration Option
Add `suppress_final_response: bool` to channel configs (similar to existing `filter_thinking` and `filter_tool_messages`):
```python
# config.py
class TelegramConfig(BaseChannelConfig):
suppress_final_response: bool = False # New option
filter_thinking: bool = True
filter_tool_messages: bool = True
```
### 2. Patch ReAct Agent Loop
In `agentscope/_react_agent.py`, after receiving tool_result but before sending to LLM for final response:
```python
# Pseudo-code
if channel_config.suppress_final_response and tool_result_received:
# Send tool output directly to channel, skip LLM final response
await channel.send(tool_result.output)
return
else:
# Existing behaviour: send to LLM for summarization
final_response = await llm.generate(tool_result)
await channel.send(final_response)
```
### 3. Console UI Toggle (Optional)
For the Console channel, add a per-session toggle in the chat interface to enable/disable this behaviour.
## Implementation Scope
| Component | Change Required |
|-----------|-----------------|
| `config.py` | Add `suppress_final_response` to channel configs |
| `agentscope/_react_agent.py` | Check flag before final LLM call |
| `channels/telegram.py` | Pass config to renderer |
| `channels/console.py` | Pass config to renderer |
| Other channels | Inherit default (False) |
## Alternatives Considered
### 1. Prompt Engineering
**Tried and failed.** Instructions like "only use the tool, don't write text" are consistently ignored by LLMs across providers (Qwen, GPT, Claude).
### 2. Post-Processing Filters
Existing `filter_tool_messages` only hides tool call metadata, not the final text response. Would need a new filter type that intercepts the final response — essentially the same as the proposed solution.
### 3. Skill-Level Suppression
Skills cannot control the agent loop. The final response happens after the skill returns, in the ReAct coordinator.
## Testing Plan
- [ ] Telegram channel with `suppress_final_response: true` sends only tool output
- [ ] Telegram channel with `suppress_final_response: false` (default) behaves as before
- [ ] Console channel supports the same toggle
- [ ] Other channels inherit default behaviour (no breaking changes)
- [ ] Multi-turn conversations work correctly when suppression is enabled
## Additional Context
**Real-world test case:** Telegram voice pipeline using Edge TTS
```
User: [sends voice message]
→ faster-whisper transcribes to text
→ Agent processes query
→ Edge TTS tool generates audio file
→ Telegram sends audio ✅
→ Telegram sends text caption "Here's your voice reply..." ❌
```
The text caption cannot be suppressed without this feature. We attempted platform-level patches to `agentscope/_react_agent.py` and `qwenpaw/runner/utils.py` but maintaining forked core files is unsustainable.
**Security considerations:** None — this is a presentation-layer feature, not a security boundary. Tool guard/approval systems remain unaffected.
---
## Priority
**Medium-High** — This blocks legitimate voice/multi-modal workflows and forces users to maintain forked core files.
---
*Note: I'm happy to contribute a PR if the maintainers can provide guidance on the preferred implementation approach.*
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.