hermes - 💡(How to fix) Fix feat: unified proxy support for all internal tools (httpx / requests / agent-browser [1 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
NousResearch/hermes-agent#17978Fetched 2026-05-01 05:54:38
View on GitHub
Comments
0
Participants
1
Timeline
8
Reactions
0
Author
Participants
Timeline (top)
labeled ×8

_get_proxy_from_env() in run_agent.py handles proxy for model API calls, but most internal tools use bare httpx/requests without proxy awareness. In proxied environments, many tools silently fail.

Additionally, Chromium does not support socks5h:// — only socks5://. When ALL_PROXY=socks5h://... is set, the browser tool fails with ERR_NO_SUPPORTED_PROXIES.

Root Cause

_get_proxy_from_env() in run_agent.py handles proxy for model API calls, but most internal tools use bare httpx/requests without proxy awareness. In proxied environments, many tools silently fail.

Additionally, Chromium does not support socks5h:// — only socks5://. When ALL_PROXY=socks5h://... is set, the browser tool fails with ERR_NO_SUPPORTED_PROXIES.

Fix Action

Fix / Workaround

Proposed Fix 1: Monkey-patch httpx/requests at startup

def _patch_proxies(): proxy = _get_proxy() if not proxy: return # httpx for cls in (httpx.AsyncClient, httpx.Client): orig = cls.init def patched(self, *a, __orig=orig, **kw): if "proxy" not in kw and "transport" not in kw: kw["proxy"] = proxy __orig(self, *a, **kw) cls.init = patched # requests orig = requests.Session.init def patched(self, *a, __orig=orig, **kw): __orig(self, *a, **kw) self.proxies = {"http": proxy, "https": proxy} requests.Session.init = patched

_patch_proxies()

Code Example

# In run_agent.py startup, inject proxy from env into all httpx/requests calls
import httpx, requests, os

def _get_proxy():
    for k in ("HTTPS_PROXY","HTTP_PROXY","ALL_PROXY","https_proxy","http_proxy","all_proxy"):
        v = os.environ.get(k,"").strip()
        if v: return v

def _patch_proxies():
    proxy = _get_proxy()
    if not proxy: return
    # httpx
    for cls in (httpx.AsyncClient, httpx.Client):
        orig = cls.__init__
        def patched(self, *a, __orig=orig, **kw):
            if "proxy" not in kw and "transport" not in kw:
                kw["proxy"] = proxy
            __orig(self, *a, **kw)
        cls.__init__ = patched
    # requests
    orig = requests.Session.__init__
    def patched(self, *a, __orig=orig, **kw):
        __orig(self, *a, **kw)
        self.proxies = {"http": proxy, "https": proxy}
    requests.Session.__init__ = patched

_patch_proxies()

---

# In browser_tool.py _run_browser_command(), after browser_env = {**os.environ}:
for k in ("ALL_PROXY","HTTPS_PROXY","HTTP_PROXY","all_proxy","https_proxy","http_proxy"):
    v = browser_env.get(k)
    if v and "socks5h" in v.lower():
        browser_env[k] = v.replace("socks5h", "socks5")
RAW_BUFFERClick to expand / collapse

Summary

_get_proxy_from_env() in run_agent.py handles proxy for model API calls, but most internal tools use bare httpx/requests without proxy awareness. In proxied environments, many tools silently fail.

Additionally, Chromium does not support socks5h:// — only socks5://. When ALL_PROXY=socks5h://... is set, the browser tool fails with ERR_NO_SUPPORTED_PROXIES.

Affected Tools

No proxy awareness (bare httpx/requests):

  • tools/vision_tools.pyhttpx.AsyncClient() (image download)
  • tools/web_tools.pyhttpx.post() (Tavily API)
  • tools/skills_hub.pyhttpx.get/post() (skill manifests)
  • tools/tts_tool.pyrequests.post() (TTS providers)
  • tools/mcp_tool.pyhttpx.AsyncClient() (SSE transport)
  • tools/send_message_tool.pyhttpx.AsyncClient() (media download)
  • tools/transcription_tools.pyrequests.post() (Whisper API)
  • tools/image_generation_tool.py — httpx via fal_client

Broken with socks5h (Chromium incompatibility):

  • tools/browser_tool.py — inherits env via browser_env = {**os.environ}, Chromium rejects socks5h scheme

Proposed Fix 1: Monkey-patch httpx/requests at startup

# In run_agent.py startup, inject proxy from env into all httpx/requests calls
import httpx, requests, os

def _get_proxy():
    for k in ("HTTPS_PROXY","HTTP_PROXY","ALL_PROXY","https_proxy","http_proxy","all_proxy"):
        v = os.environ.get(k,"").strip()
        if v: return v

def _patch_proxies():
    proxy = _get_proxy()
    if not proxy: return
    # httpx
    for cls in (httpx.AsyncClient, httpx.Client):
        orig = cls.__init__
        def patched(self, *a, __orig=orig, **kw):
            if "proxy" not in kw and "transport" not in kw:
                kw["proxy"] = proxy
            __orig(self, *a, **kw)
        cls.__init__ = patched
    # requests
    orig = requests.Session.__init__
    def patched(self, *a, __orig=orig, **kw):
        __orig(self, *a, **kw)
        self.proxies = {"http": proxy, "https": proxy}
    requests.Session.__init__ = patched

_patch_proxies()

Proposed Fix 2: Rewrite socks5h → socks5 in browser env

# In browser_tool.py _run_browser_command(), after browser_env = {**os.environ}:
for k in ("ALL_PROXY","HTTPS_PROXY","HTTP_PROXY","all_proxy","https_proxy","http_proxy"):
    v = browser_env.get(k)
    if v and "socks5h" in v.lower():
        browser_env[k] = v.replace("socks5h", "socks5")

Related

#5454, #11609, #12010, #17830

extent analysis

TL;DR

To resolve the issue, apply a monkey patch to inject proxies into httpx/requests calls or rewrite the socks5h scheme to socks5 for Chromium compatibility.

Guidance

  • Identify and apply one of the proposed fixes: either monkey-patch httpx/requests at startup or rewrite socks5h to socks5 in the browser environment.
  • Verify the fix by checking if tools that previously failed due to proxy issues now work as expected.
  • Consider the implications of each fix, such as the potential performance impact of monkey patching or the limitations of rewriting the proxy scheme.
  • Review related issues (#5454, #11609, #12010, #17830) for additional context and potential solutions.

Example

The proposed fix for monkey patching httpx/requests is provided in the issue body:

def _patch_proxies():
    proxy = _get_proxy()
    if not proxy: return
    # httpx
    for cls in (httpx.AsyncClient, httpx.Client):
        orig = cls.__init__
        def patched(self, *a, __orig=orig, **kw):
            if "proxy" not in kw and "transport" not in kw:
                kw["proxy"] = proxy
            __orig(self, *a, **kw)
        cls.__init__ = patched
    # requests
    orig = requests.Session.__init__
    def patched(self, *a, __orig=orig, **kw):
        __orig(self, *a, **kw)
        self.proxies = {"http": proxy, "https": proxy}
    requests.Session.__init__ = patched

Notes

The choice of fix depends on the specific requirements and constraints of the project. The monkey patch may have performance implications, while rewriting the proxy scheme may not be suitable for all environments.

Recommendation

Apply the monkey patch fix

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

hermes - 💡(How to fix) Fix feat: unified proxy support for all internal tools (httpx / requests / agent-browser [1 participants]