NousResearch/hermes-agent · error · SubagentLifecycleError
Unknown toolsets: {', '.join(sorted(unknown))}.
Error message
Unknown toolsets: {', '.join(sorted(unknown))}. What it means
Validation error from SubagentLifecycleManager._validate_request(): every name in request.allowed_toolsets must be a key of the TOOLSETS dict in toolsets.py. Unknown names (typos, removed toolsets, custom toolset names not registered in TOOLSETS) are reported sorted in the message.
Source
Thrown at agent/subagent_lifecycle.py:531
)
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))}."
)
enabled = getattr(parent, "enabled_toolsets", None)
if enabled is not None and not set(request.allowed_toolsets).issubset(
set(enabled)
):
raise SubagentLifecycleError(
"Requested toolsets would broaden parent permissions."
)
View on GitHub (pinned to c896c09c42)
Solutions
- Validate names against toolsets.TOOLSETS before launching and fix typos/casing.
- After upgrading Hermes, re-check that your toolset names still exist (grep TOOLSETS in toolsets.py).
- For plugin-provided toolsets, register them in the toolset registry or launch without allowed_toolsets and rely on the parent's enabled set.
Example fix
# before
request = SubagentLaunchRequest(goal=g, allowed_toolsets=["filesystem", "Web"])
# after
from toolsets import TOOLSETS
wanted = [t for t in ("file", "web") if t in TOOLSETS]
request = SubagentLaunchRequest(goal=g, allowed_toolsets=wanted) Defensive patterns
Strategy: validation
Validate before calling
from toolsets import TOOLSETS
wanted = [t for t in requested_toolsets if t in TOOLSETS]
dropped = set(requested_toolsets) - set(wanted)
if dropped:
log.warning("dropping unknown toolsets: %s", dropped)
request = SubagentLaunchRequest(goal=goal, allowed_toolsets=wanted) Type guard
from toolsets import TOOLSETS
def are_known_toolsets(names) -> bool:
return set(names) <= set(TOOLSETS) Try / catch
try:
manager.launch(request)
except SubagentLifecycleError as exc:
if str(exc).startswith("Unknown toolsets"):
request = dataclasses.replace(
request,
allowed_toolsets=[t for t in request.allowed_toolsets if t in TOOLSETS],
)
manager.launch(request)
else:
raise Prevention
- Source toolset names from toolsets.TOOLSETS, never from memory or old docs.
- Re-validate hardcoded toolset lists after every Hermes upgrade.
- Check casing — toolset keys are lower-case.
When it happens
Trigger: Passing allowed_toolsets=["filesystem"] instead of "file"; referencing a toolset that was renamed or removed in a Hermes upgrade; using a plugin toolset name that lives only in the plugin registry, not in TOOLSETS; casing mistakes ("Web" vs "web").
Common situations: Hardcoding toolset lists across Hermes versions; copying toolset names from old docs or another repo; plugin authors assuming plugin toolsets are addressable here.
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/4d2bb2597b1f538a.
Report an issue: GitHub.