Skip to content

fix(message): include target in reply suppression tracking#25757

Closed
Suko wants to merge 1 commit intoopenclaw:mainfrom
Suko:fix/message-tool-reply-suppression-target
Closed

fix(message): include target in reply suppression tracking#25757
Suko wants to merge 1 commit intoopenclaw:mainfrom
Suko:fix/message-tool-reply-suppression-target

Conversation

@Suko
Copy link
Contributor

@Suko Suko commented Feb 24, 2026

Summary

  • Problem: The message tool schema routes recipients via target, but extractMessagingToolSend only tracked args.to, so sends using target were not recorded by the reply-suppression system.
  • Why it matters: Can cause duplicate outgoing messages and leak post-tool text (e.g. NO_REPLY / reasoning) to end users on channels like Telegram, even when the agent already delivered content via the message tool.
  • What changed: extractMessagingToolSend now resolves the recipient from args.to ?? args.target for action=send / thread-reply, so suppression tracking works for both parameter names.
  • What did NOT change (scope boundary): No changes to actual message delivery, routing, provider plugins, or tool schema—only suppression tracking metadata extraction.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Reply suppression now works when the message tool call uses target (instead of to) as the routing parameter. Prevents duplicate/leaked follow-up text.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS (dev)
  • Runtime/container: Node 22.x
  • Model/provider: N/A
  • Integration/channel (if any): Messaging tool reply suppression
  • Relevant config (redacted): N/A

Steps

  1. Configure an agent that sends via the message tool using action=send and target (not to).
  2. After the tool call, the assistant outputs NO_REPLY (or any text).
  3. Observe whether a second text message is delivered to the same recipient.

Expected

  • Only the tool-delivered message is sent; the trailing assistant text is suppressed.

Actual (before)

  • Trailing assistant text could be delivered as an extra visible message because the send target wasn’t tracked.

Evidence

Human Verification (required)

  • Verified scenarios: Local static verification of the extraction logic; ran pnpm check + pnpm test:fast.
  • Edge cases checked: args.to continues to work; args.target now also works; non-send actions unaffected.
  • What you did not verify: Live Telegram delivery end-to-end.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert this PR.
  • Files/config to restore: src/agents/pi-embedded-subscribe.tools.ts
  • Known bad symptoms reviewers should watch for: Reply suppression no longer triggering, duplicate assistant text messages after message tool sends.

Risks and Mitigations

  • Risk: Incorrectly treating target as a recipient for suppression could suppress replies in unexpected edge cases.
  • Mitigation: Change is limited to toolName === "message" and action in {send, thread-reply}; still requires a string recipient and provider normalization before suppression applies.

Greptile Summary

Extends reply suppression tracking to support the target parameter in addition to to for the message tool. The message tool schema accepts both to and target as routing parameters (src/agents/tools/message-tool.ts:301-307), but extractMessagingToolSend only tracked args.to, causing suppression to miss sends routed via target. This could result in duplicate messages or leaked post-tool text on channels like Telegram.

The fix adds a fallback chain (args.to ?? args.target) to resolve the recipient from either parameter name. The change is minimal, correctly scoped to toolName === "message" with action in {send, thread-reply}, and preserves the existing normalization flow through normalizeTargetForProvider.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk - it's a targeted fix that aligns extraction logic with the existing tool schema.
  • The change is a straightforward fix that correctly handles both to and target parameters as documented in the message tool schema. The implementation uses a proper fallback chain, maintains type safety, preserves existing validation logic, and is scoped to only the message tool's send/thread-reply actions. The PR description clearly documents scope boundaries and the author verified static checks pass.
  • No files require special attention

Last reviewed commit: 6f4d0df

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

@steipete
Copy link
Contributor

Closing as superseded by #25923, which is now merged to main.

What was carried over from this PR:

  • same core fix in extractMessagingToolSend: resolve recipient from args.to ?? args.target for message tool send/thread-reply actions
  • regression coverage for target alias extraction

What #25923 additionally fixes (same incident cluster):

  • iMessage echo-loop hardening using scoped outbound messageId dedupe + text fallback
  • outbound/routing reasoning-payload suppression to prevent hidden reasoning text from leaking into channel messages
  • new iMessage echo cache and inbound-processing regression tests

Thanks for the clear, minimal patch and write-up here; it directly informed the final merged solution.

@steipete steipete closed this Feb 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: message tool: target param not tracked for reply suppression (extractMessagingToolSend only checks args.to)

2 participants