delegate_task 404 errors and provider routing fixes
NousResearch/hermes-agent · cluster 17945 · agent
Data as of
Nothing open on GitHub. Fix merged in #26824. Check it covers your case.
The short answer
- Known?
- Yes. 6 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #26824. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- Nothing open on GitHub.
Multiple bug reports and fixes addressing HTTP 404 errors from the delegate_task tool, particularly with DeepSeek and other providers. Fixes cover provider auto-detection, API mode handling for direct endpoints, and URL classification for delegation routing.
Open issues0
Open PRs0
Fixes on record
-
#26824 fix(delegation): honor api_mode + auto-detect anthropic_messages URLs
files:
hermes_cli/config.py,tests/tools/test_delegate.py,tools/delegate_tool.pyShow the diff
-
hermes_cli/config.py@@ -1146,6 +1146,10 @@ def _ensure_hermes_home_managed(home: Path): "provider": "", # e.g. "openrouter" (empty = inherit parent provider + credentials) "base_url": "", # direct OpenAI-compatible endpoint for subagents "api_key": "", # API key for delegation.base_url (falls back to OPENAI_API_KEY) + "api_mode": "", # wire protocol for delegation.base_url: "chat_completions", + # "codex_responses", or "anthropic_messages". Empty = auto-detect + # from URL (e.g. /anthropic suffix → anthropic_messages). Set this + # explicitly for non-standard endpoints the heuristic can't detect. # When delegate_task narrows child toolsets explicitly, preserve any # MCP toolsets the parent already has enabled. On by default so # narrowing (e.g. toolsets=["web","browser"]) expresses "I want these -
tests/tools/test_delegate.py@@ -890,6 +890,63 @@ def test_direct_endpoint_uses_configured_base_url_and_api_key(self): self.assertEqual(creds["api_key"], "local-key") self.assertEqual(creds["api_mode"], "chat_completions") + def test_direct_endpoint_auto_detects_anthropic_messages_suffix(self): + # Issue #10213: Azure AI Foundry exposes Anthropic-compatible models at + # a /anthropic URL suffix. Subagents must pick anthropic_messages + # automatically, matching the main agent's runtime resolver. + parent = _make_mock_parent(depth=0) + cfg = { + "model": "claude-opus-4-6", + "provider": "custom", + "base_url": "https://myfoundry.services.ai.azure.com/anthropic", + "api_key": "foundry-key", + } + creds = _resolve_delegation_credentials(cfg, parent) + self.assertEqual(creds["provider"], "custom") + self.assertEqual(creds["base_url"], "https://myfoundry.services.ai.azure.com/anthropic") + self.assertEqual(creds["api_key"], "foundry-key") + self.assertEqual(creds["api_mode"], "anthropic_messages") + + def test_direct_endpoint_honors_explicit_api_mode(self): + # When delegation.api_mode is set explicitly, it overrides URL-based + # detection so users can force a transport on non-standard endpoints. + parent = _make_mock_parent(depth=0) + cfg = { + "model": "claude-opus-4-6", + "provider": "custom", + "base_url": "https://proxy.example.com/v1", + "api_key": "proxy-key", + "api_mode": "anthropic_messages", + } + creds = _resolve_delegation_credentials(cfg, parent) + self.assertEqual(creds["api_mode"], "anthropic_messages") + + def test_direct_endpoint_explicit_api_mode_overrides_url_detection(self): + # Explicit api_mode in config always wins over auto-detection. + parent = _make_mock_parent(depth=0) + cfg = { + "model": "claude-opus-4-6", + "provider": "custom", + "base_url": "https://myfoundry.services.ai.azure.com/anthropic", + "api_key": "foundry-key", + "api_mode": "chat_completions", + } + creds = _resolve_delegation_credentials(cfg, parent) + self.assertEqual(creds["api_mode"], "chat_completions") + + def test_direct_endpoint_invalid_api_mode_falls_back_to_detection(self): + # An invalid api_mode string must not break detection; fall back to URL heuristic. + parent = _make_mock_parent(depth=0) + cfg = { + "model": "claude-opus-4-6", + "provider": "custom", + "base_url": "https://myfoundry.services.ai.azure.com/anthropic", + "api_key": "foundry-key", + "api_mode": "garbage", + } + creds = _resolve_delegation_credentials(cfg, parent) + self.assertEqual(creds["api_mode"], "anthropic_messages") + def test_direct_endpoint_returns_none_api_key_when_not_configured(self): # When base_url is set without api_key, api_key should be None so # _build_child_agent inherits the parent's key (effective_api_key = override or parent). -
tools/delegate_tool.py@@ -2362,6 +2362,7 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict: configured_provider = str(cfg.get("provider") or "").strip() or None configured_base_url = str(cfg.get("base_url") or "").strip() or None configured_api_key = [redacted:secret-assignment]"api_key") or "").strip() or None + configured_api_mode = str(cfg.get("api_mode") or "").strip().lower() or None if configured_base_url: # When delegation.api_key is not set, return None so _build_child_agent @@ -2372,9 +2373,17 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict: # callers to duplicate the key under delegation.api_key. api_key = [redacted:secret-assignment] # None → inherited from parent in _build_child_agent + # Use the shared URL-based api_mode detector (same path the main agent's + # runtime resolver uses) so Anthropic-compatible direct endpoints with a + # /anthropic suffix — Azure AI Foundry, MiniMax, Zhipu GLM, LiteLLM + # proxies — pick the right transport automatically. Without this, + # subagents would default to chat_completions and hit 404s on endpoints + # that only speak the Anthropic Messages protocol. Fixes #10213. + from hermes_cli.runtime_provider import _detect_api_mode_for_url + base_lower = configured_base_url.lower() provider = "custom" - api_mode = "chat_completions" + api_mode = _detect_api_mode_for_url(configured_base_url) or "chat_completions" if ( base_url_hostname(configured_base_url) == "chatgpt.com" and "/backend-api/codex" in base_lower @@ -2388,6 +2397,11 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict: provider = "custom" api_mode = "anthropic_messages" + # Explicit delegation.api_mode in config always wins. Lets users force + # a transport for non-standard endpoints the URL heuristic can't detect. + if configured_api_mode in {"chat_completions", "codex_responses", "anthropic_messages"}: + api_mode = configured_api_mode + return { "model": configured_model, "provider": provider,
-
3 PRs closed without merging
From the close comments: done elsewhere 1 · other 2
-
#26331 fix(delegate): honor custom provider api mode for direct endpoints · other →
#10273,#5697,#11756 -
#26376 fix(delegate): honor api mode for direct endpoints · other →
#26210,#26331 -
#33324 fix(tools): recognize api.deepseek.com as deepseek provider in delegate_task · done elsewhere →
c445f48,#26824
Closed issues · 2
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.29: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- agent
- Merged PRs
- #26824
- Closed issues
- 2
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 16 May 2026