openclaw - ✅(Solved) Fix bug: sessions_send A2A announce drops threadId on sessions.list fallback [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#63469Fetched 2026-04-09 07:53:25
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
cross-referenced ×2commented ×1referenced ×1

Sub-agent / agent-to-agent announce delivery can lose the originating thread/topic when the announce target is resolved via sessions.list fallback.

This causes completion messages to land in the parent channel top-level instead of the originating Telegram forum topic / thread.

Root Cause

  1. resolveAnnounceTarget() falls back to sessions.list when the channel/plugin prefers session lookup.
  2. In that branch it hydrates channel, to, and accountId, but drops threadId even when it exists in:
    • deliveryContext.threadId
    • or match.lastThreadId
  3. runSessionsSendA2AFlow() then calls gateway send without threadId.

So the announce still knows the chat target, but loses the thread/topic target.

Fix Action

Fixed

PR fix notes

PR #63506: fix(agents): preserve announce threadId on sessions.list fallback

Description (problem / solution / changelog)

Summary

  • preserve threadId when resolveAnnounceTarget() falls back to sessions.list
  • carry deliveryContext.threadId and lastThreadId through announce target hydration
  • add regression coverage for both target resolution and final A2A announce delivery

Root cause

The legacy A2A announce fallback rehydrated channel, to, and accountId from sessions.list, but it dropped thread/topic context. As a result, final announce deliveries were sent to the top-level channel instead of the originating thread/topic.

Verification

  • pnpm test -- src/agents/tools/sessions.test.ts src/agents/openclaw-tools.sessions.test.ts
  • pnpm exec oxfmt --check src/agents/tools/sessions-helpers.ts src/agents/tools/sessions-announce-target.ts src/agents/tools/sessions.test.ts src/agents/openclaw-tools.sessions.test.ts

Closes #63469

Changed files

  • src/agents/openclaw-tools.sessions.test.ts (modified, +198/-0)
  • src/agents/tools/sessions-announce-target.ts (modified, +5/-1)
  • src/agents/tools/sessions-helpers.ts (modified, +1/-0)
  • src/agents/tools/sessions.test.ts (modified, +4/-0)
RAW_BUFFERClick to expand / collapse

Summary

Sub-agent / agent-to-agent announce delivery can lose the originating thread/topic when the announce target is resolved via sessions.list fallback.

This causes completion messages to land in the parent channel top-level instead of the originating Telegram forum topic / thread.

Affected path

The regression is in the legacy A2A announce flow:

  • src/agents/tools/sessions-announce-target.ts
  • src/agents/tools/sessions-send-tool.a2a.ts

Root cause

  1. resolveAnnounceTarget() falls back to sessions.list when the channel/plugin prefers session lookup.
  2. In that branch it hydrates channel, to, and accountId, but drops threadId even when it exists in:
    • deliveryContext.threadId
    • or match.lastThreadId
  3. runSessionsSendA2AFlow() then calls gateway send without threadId.

So the announce still knows the chat target, but loses the thread/topic target.

Repro

  1. Start from a threaded/topic conversation (for example Telegram forum topic).
  2. Trigger a flow that returns through the legacy A2A announce path.
  3. Wait for the sub-agent / delegated response to announce back.
  4. Observe the final announce is delivered to the channel top-level instead of the originating thread/topic.

Expected

When thread/topic context exists in session delivery metadata, the announce target should preserve it and the final send should include threadId.

Actual

threadId is dropped during target resolution and never sent.

Related

This appears to be in the same family as:

  • #21162
  • #26867
  • #27445
  • #33478
  • #52217

But this issue is narrower and specifically covers the legacy sessions_send A2A announce path dropping threadId on sessions.list fallback.

Proposed fix

  • In resolveAnnounceTarget(), preserve threadId from deliveryContext.threadId or match.lastThreadId.
  • In runSessionsSendA2AFlow(), pass threadId into the final gateway send call when present.
  • Add regression tests covering both behaviors.

extent analysis

TL;DR

Preserve the threadId in the resolveAnnounceTarget() function and pass it to the final gateway send call to fix the issue.

Guidance

  • Review the resolveAnnounceTarget() function in src/agents/tools/sessions-announce-target.ts to ensure it preserves the threadId from deliveryContext.threadId or match.lastThreadId.
  • Update the runSessionsSendA2AFlow() function in src/agents/tools/sessions-send-tool.a2a.ts to pass the threadId to the final gateway send call when present.
  • Add regression tests to cover both the preservation of threadId and its inclusion in the final send call.
  • Verify the fix by reproducing the issue using the steps in the "Repro" section and checking that the final announce is delivered to the correct thread/topic.

Example

// In resolveAnnounceTarget()
if (deliveryContext.threadId) {
  target.threadId = deliveryContext.threadId;
} else if (match.lastThreadId) {
  target.threadId = match.lastThreadId;
}

// In runSessionsSendA2AFlow()
if (target.threadId) {
  gateway.send({ ...message, threadId: target.threadId });
} else {
  gateway.send(message);
}

Notes

This fix assumes that the threadId is correctly set in the deliveryContext or match objects. Additional debugging may be necessary if the issue persists after applying this fix.

Recommendation

Apply the proposed fix to preserve the threadId and pass it to the final gateway send call, as this directly addresses the root cause of the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING