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

  1. Validate names against toolsets.TOOLSETS before launching and fix typos/casing.
  2. After upgrading Hermes, re-check that your toolset names still exist (grep TOOLSETS in toolsets.py).
  3. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/4d2bb2597b1f538a. Report an issue: GitHub.