headroomlabs-ai/headroom · error · KeyError
Unknown agent: {name!r}. Available: {available}
Error message
Unknown agent: {name!r}. Available: {available} What it means
Raised by headroom.learn.registry.get_plugin when the requested agent plugin name is not in the discovered registry. Discovery scans built-in modules in headroom/learn/plugins (claude, codex, gemini, grok, opencode, ...) plus external entry_points(group="headroom.learn_plugin"), and the error message lists every name that IS available so the correct one is obvious.
Source
Thrown at headroom/learn/registry.py:86
"""Get the plugin registry, discovering plugins on first call.
Returns a name → LearnPlugin mapping of all available plugins.
"""
global _registry
if _registry is None:
_registry = _discover()
return _registry
def get_plugin(name: str) -> LearnPlugin:
"""Look up a plugin by name.
Raises KeyError with a helpful message if not found.
"""
reg = get_registry()
if name not in reg:
available = ", ".join(sorted(reg.keys()))
raise KeyError(f"Unknown agent: {name!r}. Available: {available}")
return reg[name]
def auto_detect_plugins() -> list[LearnPlugin]:
"""Return plugins that have data on the current machine.
Calls ``detect()`` on each registered plugin and filters to those
that return True.
"""
return [p for p in get_registry().values() if p.detect()]
def available_agent_names() -> list[str]:
"""Return sorted list of all registered agent names."""
return sorted(get_registry().keys())
def reset_registry() -> None:View on GitHub (pinned to 322425c43b)
Solutions
- Read the 'Available:' list in the message and use one of those exact names (case-sensitive).
- If the plugin should exist, check it's a LearnPlugin instance and importable in the current interpreter; watch for the registry's warning log about skipped plugins.
- For external plugins, verify the entry point group is 'headroom.learn_plugin' and the package is installed in the active environment.
- Restart the process if you installed a new plugin while a long-lived session was running (registry is cached after first discovery).
Example fix
# before
from headroom.learn.registry import get_plugin
get_plugin("Claude") # KeyError: Unknown agent: 'Claude'. Available: claude, codex, ...
# after
get_plugin("claude") # exact lowercase name from the Available list Defensive patterns
Strategy: validation
Validate before calling
from headroom.learn.registry import get_registry
wanted = "claude"
available = get_registry()
if wanted not in available:
raise SystemExit(f"unknown agent {wanted!r}; choose from {sorted(available)}")
plugin = available[wanted] Type guard
from headroom.learn.registry import get_registry
from headroom.learn.base import LearnPlugin
def is_known_agent(name: str) -> bool:
"""True if name is a discoverable learn plugin (case-sensitive)."""
return name in get_registry() Try / catch
from headroom.learn.registry import get_plugin
try:
plugin = get_plugin(name)
except KeyError as e:
# message lists available names; parse-free UX: print and exit
raise SystemExit(str(e)) from None Prevention
- Derive agent names from get_registry().keys() instead of hardcoding strings.
- Treat names as case-sensitive lowercase identifiers.
- After installing a new learn plugin, start a fresh process — the registry caches after first discovery.
When it happens
Trigger: Calling get_plugin(name) / CLI `--agent <name>` with a typo or wrong casing (e.g. 'Claude' instead of 'claude'), or requesting an agent whose plugin module failed to import during discovery, or an external plugin whose entry point is not installed in the current environment.
Common situations: Typo'd or capitalized agent names on the command line; running in a venv where a third-party headroom learn plugin isn't installed; plugin module raising during import so it's silently skipped with a log warning; stale process started before a new plugin was installed.
Related errors
- Error: {e}
- compressor descriptor.name must be non-empty
- compressor {name!r} is already registered
- headroom-oauth2 misconfigured: {e}
- Headroom OpenCode transport shim loaded without HEADROOM_OPE
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/de0bb26d341499bd.
Report an issue: GitHub.