NousResearch/hermes-agent · error · SubagentLifecycleError
Per-tool blocking is not supported; use allowed_toolsets. He
Error message
Per-tool blocking is not supported; use allowed_toolsets. Hermes always blocks unsafe child tools.
What it means
Validation error from SubagentLifecycleManager._validate_request(): per-tool blocking is not supported. If request.blocked_tools is truthy the launch is rejected; the security model is allow-list based — restrict a child via allowed_toolsets, and Hermes itself always strips unsafe tools from children.
Source
Thrown at agent/subagent_lifecycle.py:515
if request.context is not None and (
not isinstance(request.context, str)
or len(request.context) > _MAX_CONTEXT_CHARS
):
raise SubagentLifecycleError(
"context must be a string of at most 32000 characters."
)
if request.role not in {"leaf", "orchestrator"}:
raise SubagentLifecycleError("role must be 'leaf' or 'orchestrator'.")
if request.timeout_seconds is not None:
raise SubagentLifecycleError(
"Per-launch timeout is not supported; configure delegation timeout explicitly."
)
if request.working_directory is not None:
raise SubagentLifecycleError(
"working_directory is not supported because Hermes delegates use isolated task environments."
)
if request.blocked_tools:
raise SubagentLifecycleError(
"Per-tool blocking is not supported; use allowed_toolsets. Hermes always blocks unsafe child tools."
)
try:
metadata_bytes = len(
json.dumps(dict(request.metadata), sort_keys=True).encode()
)
except (TypeError, ValueError) as exc:
raise SubagentLifecycleError("metadata must be JSON-serializable.") from exc
if metadata_bytes > _MAX_METADATA_BYTES:
raise SubagentLifecycleError("metadata exceeds 8192 bytes.")
if request.allowed_toolsets:
from toolsets import TOOLSETS
unknown = set(request.allowed_toolsets) - set(TOOLSETS)
if unknown:
raise SubagentLifecycleError(
f"Unknown toolsets: {', '.join(sorted(unknown))}."
)View on GitHub (pinned to c896c09c42)
Solutions
- Use allowed_toolsets with an explicit allow list (e.g. ["search", "file"]) instead of a deny list.
- Clear blocked_tools entirely (empty list or None-equivalent) on every request.
- Rely on Hermes' built-in child hardening for unsafe tools rather than adding your own deny list.
Example fix
# before request = SubagentLaunchRequest(goal=g, blocked_tools=["terminal", "browser_navigate"]) # after request = SubagentLaunchRequest(goal=g, allowed_toolsets=["search", "file", "web"])
Defensive patterns
Strategy: validation
Validate before calling
request = SubagentLaunchRequest(
goal=goal,
allowed_toolsets=["search", "file"], # allow-list, not deny-list
blocked_tools=None,
) Try / catch
try:
manager.launch(request)
except SubagentLifecycleError as exc:
if "Per-tool blocking" in str(exc):
request = dataclasses.replace(request, blocked_tools=None)
manager.launch(request)
else:
raise Prevention
- Model child restrictions as an allow-list via allowed_toolsets.
- Never populate blocked_tools, even with placeholder values.
- Trust Hermes' built-in stripping of unsafe child tools.
When it happens
Trigger: Setting SubagentLaunchRequest(blocked_tools=["terminal"]) expecting a read-only child; porting a deny-list security policy from another framework; populating blocked_tools with an empty-but-truthy value like [""] or [None].
Common situations: Trying to sandbox children by denying dangerous tools; policy engines that always emit a blocked list (even empty-looking); misunderstanding that a truthy-but-useless list still trips the check.
Related errors
- parent_session_id does not match the active session.
- goal must be a non-empty string of at most 16000 characters.
- context must be a string of at most 32000 characters.
- role must be 'leaf' or 'orchestrator'.
- Per-launch timeout is not supported; configure delegation ti
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/8d296841bef6b9da.
Report an issue: GitHub.