{"record":{"id":"de0bb26d341499bd","repo":"headroomlabs-ai/headroom","slug":"unknown-agent-name-r-available-available","errorCode":null,"errorMessage":"Unknown agent: {name!r}. Available: {available}","messagePattern":"Unknown agent: (.+?)\\. Available: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"headroom/learn/registry.py","lineNumber":86,"sourceCode":"    \"\"\"Get the plugin registry, discovering plugins on first call.\n\n    Returns a name → LearnPlugin mapping of all available plugins.\n    \"\"\"\n    global _registry\n    if _registry is None:\n        _registry = _discover()\n    return _registry\n\n\ndef get_plugin(name: str) -> LearnPlugin:\n    \"\"\"Look up a plugin by name.\n\n    Raises KeyError with a helpful message if not found.\n    \"\"\"\n    reg = get_registry()\n    if name not in reg:\n        available = \", \".join(sorted(reg.keys()))\n        raise KeyError(f\"Unknown agent: {name!r}. Available: {available}\")\n    return reg[name]\n\n\ndef auto_detect_plugins() -> list[LearnPlugin]:\n    \"\"\"Return plugins that have data on the current machine.\n\n    Calls ``detect()`` on each registered plugin and filters to those\n    that return True.\n    \"\"\"\n    return [p for p in get_registry().values() if p.detect()]\n\n\ndef available_agent_names() -> list[str]:\n    \"\"\"Return sorted list of all registered agent names.\"\"\"\n    return sorted(get_registry().keys())\n\n\ndef reset_registry() -> None:","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/learn/registry.py#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before\nfrom headroom.learn.registry import get_plugin\nget_plugin(\"Claude\")  # KeyError: Unknown agent: 'Claude'. Available: claude, codex, ...\n\n# after\nget_plugin(\"claude\")  # exact lowercase name from the Available list","handlingStrategy":"validation","validationCode":"from headroom.learn.registry import get_registry\n\nwanted = \"claude\"\navailable = get_registry()\nif wanted not in available:\n    raise SystemExit(f\"unknown agent {wanted!r}; choose from {sorted(available)}\")\nplugin = available[wanted]","typeGuard":"from headroom.learn.registry import get_registry\nfrom headroom.learn.base import LearnPlugin\n\ndef is_known_agent(name: str) -> bool:\n    \"\"\"True if name is a discoverable learn plugin (case-sensitive).\"\"\"\n    return name in get_registry()","tryCatchPattern":"from headroom.learn.registry import get_plugin\n\ntry:\n    plugin = get_plugin(name)\nexcept KeyError as e:\n    # message lists available names; parse-free UX: print and exit\n    raise SystemExit(str(e)) from None","preventionTips":["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."],"tags":["plugin","registry","learn","configuration"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}