diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py
index 0b1f97046b84..edc2e008178d 100644
--- a/hermes_cli/gateway.py
+++ b/hermes_cli/gateway.py
@@ -3090,7 +3090,19 @@ def generate_launchd_plist() -> str:
SuccessfulExit
-
+
+ SoftResourceLimits
+
+ NumberOfFiles
+ 65536
+
+
+ HardResourceLimits
+
+ NumberOfFiles
+ 65536
+
+
StandardOutPath
{log_dir}/gateway.log
diff --git a/tests/hermes_cli/test_gateway_service.py b/tests/hermes_cli/test_gateway_service.py
index c6baa7156324..da769e429e93 100644
--- a/tests/hermes_cli/test_gateway_service.py
+++ b/tests/hermes_cli/test_gateway_service.py
@@ -1629,6 +1629,20 @@ def test_launchd_plist_includes_profile(self, tmp_path, monkeypatch):
assert "--profile" in plist
assert "mybot" in plist
+ def test_launchd_plist_sets_nofiles_resource_limits(self, tmp_path, monkeypatch):
+ """generate_launchd_plist must set NumberOfFiles limits so the long-running
+ gateway doesn't hit launchd's default 256 soft RLIMIT_NOFILE (issue #36899)."""
+ profile_dir = tmp_path / ".hermes"
+ profile_dir.mkdir(parents=True)
+ monkeypatch.setattr(Path, "home", lambda: tmp_path)
+ monkeypatch.setenv("HERMES_HOME", str(profile_dir))
+ monkeypatch.setattr(gateway_cli, "get_hermes_home", lambda: profile_dir)
+ plist = gateway_cli.generate_launchd_plist()
+ assert "SoftResourceLimits" in plist
+ assert "HardResourceLimits" in plist
+ assert plist.count("NumberOfFiles") == 2
+ assert plist.count("65536") >= 2
+
def test_launchd_plist_path_uses_real_user_home_not_profile_home(self, tmp_path, monkeypatch):
profile_dir = tmp_path / ".hermes" / "profiles" / "orcha"
profile_dir.mkdir(parents=True)