Skip to content

fix(agents,gateway): keep subagent announces in the original thread#63143

Merged
jalehman merged 3 commits into
openclaw:mainfrom
mariosousa-finn:fix/subagent-delivery-context-v2
Apr 10, 2026
Merged

fix(agents,gateway): keep subagent announces in the original thread#63143
jalehman merged 3 commits into
openclaw:mainfrom
mariosousa-finn:fix/subagent-delivery-context-v2

Conversation

@mariosousa-finn

Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: subagent sessions created without an initial delivery context could lose the caller's to / threadId, and later A2A announce delivery also dropped threadId when resolving the target from sessions.list.
  • Why it matters: subagent completion/announce messages can drift to the wrong destination or escape to a top-level channel instead of staying in the original thread/topic.
  • What changed: seed new subagent session delivery context from the spawn request, preserve resolved announce threadId, and include that threadId in the gateway send call.
  • What did NOT change (scope boundary): this does not change announce content, channel-specific formatting, or unrelated session routing behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • 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

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: newly spawned subagent sessions could be persisted before they had a usable deliveryContext, so announce delivery later depended on mutable legacy last* fields; separately, resolveAnnounceTarget() extracted thread information but returned only { channel, to, accountId }, and the A2A announce send call also omitted threadId.
  • Missing detection / guardrail: there was no regression test covering a thread-scoped subagent spawn followed by announce delivery through the sessions.list lookup path.
  • Contributing context (if known): this showed up in the v2026.4.x path where thread-scoped announce delivery relies on reconstructed session routing metadata.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
    • src/gateway/server.agent.subagent-delivery-context.test.ts
    • src/agents/tools/sessions.test.ts
    • src/agents/tools/sessions-send-tool.a2a.test.ts
  • Scenario the test should lock in: a subagent spawned from a threaded request keeps the original routing context, and a later announce send still includes the thread/topic id.
  • Why this is the smallest reliable guardrail: it covers both the persistence boundary in the gateway and the announce-delivery lookup/send path without depending on a live channel integration.
  • Existing test that already covers this (if any): the gateway delivery-context tests already covered the spawn-side behavior; this PR extends announce-path coverage.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

  • Subagent completion/announce messages stay in the same thread/topic more reliably instead of falling back to a top-level destination.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[threaded request] -> [subagent session persisted without complete delivery context]
                 -> [announce target reconstructed without threadId]
                 -> [announce sent without threadId] -> [wrong/top-level destination]

After:
[threaded request] -> [subagent session seeded with channel/to/threadId]
                 -> [announce target keeps threadId]
                 -> [announce send includes threadId] -> [original thread/topic]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local repo checkout
  • Model/provider: N/A
  • Integration/channel (if any): thread-scoped session routing / agent-to-agent announce flow
  • Relevant config (redacted): default local test harness config

Steps

  1. Spawn a subagent from a threaded request where the subagent session does not yet have a delivery context.
  2. Let announce target resolution fall back to sessions.list.
  3. Send the A2A announce reply.

Expected

  • The subagent session keeps the request channel, to, accountId, and threadId.
  • The resolved announce target includes threadId.
  • The gateway send call includes threadId.

Actual

  • Before this change, announce resolution/send could lose threadId, causing delivery to miss the original thread/topic.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: ran targeted vitest coverage for gateway subagent delivery-context seeding, announce-target resolution, and A2A announce send propagation.
  • Edge cases checked: existing session delivery context is not overwritten; request without to/threadId does not inject empty values; announce target can hydrate threadId from deliveryContext / lastThreadId / origin.threadId.
  • What you did not verify: live channel integration behavior against a production workspace.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: thread/topic ids now flow through announce resolution in more cases, including numeric values from legacy session rows.
    • Mitigation: the code normalizes routed thread ids to strings and adds targeted regression coverage for both resolution and send.
  • Risk: new-session seeding could accidentally override an existing delivery context.
    • Mitigation: the gateway path merges request hints only as fallback values and existing delivery context remains authoritative, with regression coverage.

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime agents Agent runtime and tooling size: M labels Apr 8, 2026
@greptile-apps

greptile-apps Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two related bugs in the subagent announce delivery path: (1) newly spawned subagent sessions could be persisted with an incomplete deliveryContext (missing to/threadId), and (2) resolveAnnounceTarget did not return threadId when falling back to sessions.list, causing the downstream send call to omit it. The fix seeds missing delivery context from the spawn request using primary-wins merge semantics, extracts and propagates threadId through the announce resolution, and passes it in the gateway send call. Test coverage is added for all three paths.

Confidence Score: 5/5

This PR is safe to merge — the fix is well-scoped, uses primary-wins merge semantics to avoid overwriting existing delivery context, and includes regression tests for all three changed paths.

All findings are P2 or lower. The gateway seeding logic correctly guards existing delivery context via mergeDeliveryContext with primary-wins semantics. The resolveAnnounceTarget threadId extraction is numerically safe and mirrors the pattern used elsewhere. The send call now forwards threadId that was previously silently dropped. Test coverage is solid across the new paths.

No files require special attention.

Vulnerabilities

No security concerns identified. The change only propagates existing routing metadata (threadId, to, channel, accountId) that was already present in the request or session — no new attack surface, no secrets handling, no new network calls, and no privilege escalation.

Reviews (1): Last reviewed commit: "fix(agents): preserve announce thread id..." | Re-trigger Greptile

@mariosousa-finn mariosousa-finn force-pushed the fix/subagent-delivery-context-v2 branch from 68d5bb9 to 6e49bf3 Compare April 8, 2026 12:39
@jalehman jalehman self-assigned this Apr 9, 2026
@jalehman jalehman force-pushed the fix/subagent-delivery-context-v2 branch 4 times, most recently from ee0be74 to 0c593cc Compare April 10, 2026 22:43
@jalehman jalehman force-pushed the fix/subagent-delivery-context-v2 branch from 0c593cc to 9aa5303 Compare April 10, 2026 22:45
@jalehman jalehman merged commit ac13b09 into openclaw:main Apr 10, 2026
8 checks passed
@jalehman

Copy link
Copy Markdown
Contributor

Merged via squash.

Thanks @mariosousa-finn!

lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…penclaw#63143)

Merged via squash.

Prepared head SHA: 9aa5303
Co-authored-by: mariosousa-finn <244526439+mariosousa-finn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling gateway Gateway runtime size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants