Skip to content

fix(delegation): keep nested work on its coordinator route - #109699

Closed
Lei-k wants to merge 1 commit into
NousResearch:mainfrom
Lei-k:fix/upstream-delegation-route-ownership
Closed

Lei-k wants to merge 1 commit into
NousResearch:mainfrom
Lei-k:fix/upstream-delegation-route-ownership

Conversation

@Lei-k

@Lei-k Lei-k commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Keeps a delegated worker from taking ownership of its coordinator's conversation route in two related cases:

  • A delegate/branch created after its parent ended for compression no longer inherits the parent's gateway routing columns. A genuine compression continuation still inherits them. The exclusion compares each fork marker with the immediate parent ID, rather than rejecting inherited ancestral markers indiscriminately.
  • A nested delegate_task(background=true) inside a delegated-child context runs inline, so the requesting worker receives its own results instead of detaching them onto the coordinator's chat/history route. Normal route-owning sessions retain background delegation.

Related issue and provenance

Refs #92859 (duplicate live routing keys; this does not claim to fix every cause).

Selectively adapted from Lei-k#22, source commit 0fd2bd67daa9420bf89a14d5393b84114a33e293, merged in the fork as e54e3bae9ac1e33cff1c25bab4d681c532d8be2c. Source authorship is preserved.

The fork owner reports a week of successful operation. That is user-reported fork experience, not an upstream end-to-end validation claim.

Scope and deduplication

Based on upstream main b6b53c69a6ed49cb099cf1bfe76b5e6edd718e5a, not fork main. Only four files change. No schema migration, config, dependency, workflow, deployment or runtime changes.

This is deliberately not a wholesale cherry-pick:

The separate gateway connection wording change from fork #16 is not bundled, in accordance with the contributing guide's one-logical-change rule. Its reset recovery/status dedup portions overlap existing upstream submissions and are not reintroduced here.

Verification

Canonical runner, isolated local environment, bounded workers:

scripts/run_tests.sh -j 2 tests/state/test_delegate_child_routing_inheritance.py tests/tools/test_nested_delegation_inline_fallback.py tests/gateway/test_async_delegation_session_binding.py tests/gateway/test_async_delivery_capability.py tests/gateway/test_api_delegation_delivery_contract.py tests/gateway/test_session_context_inheritance.py tests/gateway/test_branch_routing_columns.py tests/gateway/test_delegation_session_id_leak.py
  • Final focused gate: 28 passed, 0 failed, 8 files, exit 0.
  • New invariant tests on unchanged upstream implementation: 3 failed, 1 passed; candidate: 4 passed. Real temporary SQLite SessionDB for routing; nested dispatch uses real dispatch/aggregation with the model-calling worker stubbed.
  • State siblings (tests/state/ tests/hermes_state/): 527 passed, 9 skipped, 64 files.
  • Delegation-tool siblings: 212 passed, 1 skipped, 12 files.
  • Ruff on all changed Python files and git diff --check: passed.
  • Broader gateway/state run was not green: tests/test_hermes_state.py exceeded the per-file timeout. A longer rerun was interrupted; no full-suite pass is claimed. No live provider, gateway transport or production E2E was exercised.
  • Independent read-only review of 5c7bb4897bdb540562a47d5776a2460be72d9a60: PASS, no blocking findings, with real temporary-DB and dispatch-context probes. Two non-blocking notes remain for maintainer review: fallback-note line wrapping, and the branch-marker test being a defensive SQL invariant rather than an observed gateway branch failure. Nested inline work consumes the worker's timeout budget, consistent with merged fix(delegate): nested orchestrators get their workers' results back — delegate_task exempt from the 420 s tool deadline; summary budget uses current prompt, not the session sum #103486. This Draft is for maintainer/user review, not approval to merge.

Checklist

  • Read the contributing guide; kept the change focused.
  • Added behavior regressions demonstrated failing on upstream base.
  • Preserved upstream API history-consumer behavior and normal background delegation.
  • Disclosed AI-assisted implementation and independent AI review.
  • Full repository suite passes (not claimed; timeout/incomplete broad gates described above).
  • Live transport/provider E2E (not performed).

Selectively port the nested inline fallback and compression-edge routing exclusion from #22. Preserve upstream API history-consumer handling and terminal process handoff notifications; omit overlapping route-rebinding changes.

Adapted from commit 0fd2bd6 (fork merge e54e3ba).
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists tool/delegate Subagent delegation area/sessions Session lifecycle, resume, persistence, history comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Sep 13, 2026
@Lei-k
Lei-k marked this pull request as ready for review September 14, 2026 16:37
teknium1 pushed a commit that referenced this pull request Sep 20, 2026
… parent's gateway routing

_INHERIT_PARENT_ROUTING_SQL copied session_key/chat_id/chat_type/thread_id/user_id/
display_name/origin_json/transport_profile onto ANY child whose parent row ended on
'compression'. A delegate or branch fork of such a parent is not that conversation's
continuation, so it must not take over the route: two live rows holding one routing key
lets peer recovery repoint gateway traffic into a subagent's transcript (#116322).

Exclude children whose `_delegate_from` / `_branched_from` marker names the queried parent
id. Value-match rather than presence: a compression continuation inherits model_config
verbatim (marker included), so a presence check would misclassify it — the same idiom
_NON_CONTINUATION_CHILD_FILTER_SQL already uses.

Cherry-picked from #109699 (Lei-k) minus its unrelated tools/delegate_tool_dispatch.py
nested-dispatch hunk; test relocated to tests/hermes_state/ where the suite now lives.
teknium1 added a commit that referenced this pull request Sep 20, 2026
…its its route

Pins the reason the exclusion matches the marker's VALUE against the parent id instead
of its presence: a continuation copies model_config verbatim, so a `_branched_from`
marker rides along. A presence check (#116377's variant) would leave the continuation
unroutable — exactly the shape this test fails on against that branch.

Salvages #109699 (@Lei-k). Supersedes #116377 (@strzhao).

Co-authored-by: strzhao <strzhao@users.noreply.github.com>
@Lei-k

Lei-k commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Closing after revalidation against upstream main 9573f44; no successor PR is needed.

The DB routing-inheritance part is now covered by merged #116740 (which closes #116322).

For the remaining nested-dispatch part, my earlier direct _dispatch_background regression bypassed the authoritative model-facing depth gate. Testing the actual AIAgent._execute_tool_calls entrypoint and registry fallback gives 6 passing cases: depth 0 selects background=True, while depths 1 and 2 select background=False. The coordinator independently reran all six against that exact main SHA. This validates dispatch selection with delegate_task stubbed, not a live-provider E2E claim.

Related lineage reviewed: #96424, #103486, #115616, and #52756; #109744/#109730 also clarify the existing model-facing contract. The private-function test failing alone is therefore not evidence of a reachable model-path defect, and adding another policy gate here would duplicate existing behavior.

Thank you for the upstream fixes. This closes the superseded/redundant proposal without claiming that this PR itself was merged. AI-assisted revalidation.

@Lei-k Lei-k closed this Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants