fix(delegate): resolve custom-endpoint subagent pools by endpoint identity#41730
Conversation
…ntity Subagents delegated to a custom endpoint were misrouted when the parent ran on a different custom endpoint. Both runtimes collapse to provider="custom", so _resolve_child_credential_pool() treated them as interchangeable and handed the child the parent's pool. Leasing from it then overwrote the child's delegated base_url with the parent's endpoint via _swap_credential() — the child sent the delegated model name to the wrong endpoint. Custom runtimes now resolve by endpoint identity (the custom:<name> pool key derived from base_url). The parent pool is reused only when both parent and child resolve to the same custom endpoint; unregistered raw endpoints return None so the child keeps its fixed delegated credential. Non-custom provider paths are unchanged. Fixes #7833.
🔎 Lint report:
|
|
✅ Verified — custom-endpoint identity resolution for credential pools Reviewed the diff (3 files, ~120 lines including tests). Findings:
No issues found. LGTM. |
…ntity (NousResearch#41730) Subagents delegated to a custom endpoint were misrouted when the parent ran on a different custom endpoint. Both runtimes collapse to provider="custom", so _resolve_child_credential_pool() treated them as interchangeable and handed the child the parent's pool. Leasing from it then overwrote the child's delegated base_url with the parent's endpoint via _swap_credential() — the child sent the delegated model name to the wrong endpoint. Custom runtimes now resolve by endpoint identity (the custom:<name> pool key derived from base_url). The parent pool is reused only when both parent and child resolve to the same custom endpoint; unregistered raw endpoints return None so the child keeps its fixed delegated credential. Non-custom provider paths are unchanged. Fixes NousResearch#7833.
Summary
Subagents delegated to a custom endpoint now stay on that endpoint instead of being silently rebound to the parent's custom endpoint.
Root cause: every direct
delegation.base_urlruntime collapses toprovider="custom"._resolve_child_credential_pool()shared the parent's pool whenevereffective_provider == parent_provider, so two different custom endpoints looked identical. The child then leased a parent-pool entry and_swap_credential()overwrote its delegatedbase_urlwith the parent's endpoint — sending the delegated model name to the wrong place.Changes
tools/delegate_tool.py:_resolve_child_credential_pool()resolves custom runtimes by endpoint identity (custom:<name>key frombase_url). Parent pool reused only when parent and child resolve to the same custom endpoint; unregistered raw endpoints returnNoneso the child keeps its fixed delegated credential. Threadedeffective_base_urlinto the helper at the call site.agent/credential_pool.py:get_custom_provider_pool_key()acceptsOptional[str](it already no-op'd on falsy input).tests/tools/test_delegate.py: 3 new cases — different endpoint no bleed, same endpoint shares, unregistered endpoint returns None.Validation
delegation.base_urltests/tools/test_delegate.py: 140 passed. E2E with isolated HERMES_HOME + two custom endpoints inauth.jsonconfirmed no pool bleed and correct same-endpoint sharing.Fixes #7833.
Infographic