fix(hub): report file-based custom agents' real health, not always 'error'#2277
Merged
Conversation
…rror' gaia agent status ran the installed-wheel entry-point probe against every custom_python agent, which have no entry point by construction, so all of them reported HEALTH: error even when they run fine. Add a custom_python branch to _default_loader: the registry's own successful discovery is the health signal (same as builtin), hardened by an __abstractmethods__ check so an agent that never implements _register_tools still reports error naming the real cause — without constructing the agent. Closes #2268
kovtcharov-amd
approved these changes
Jul 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every file-based custom agent (
~/.gaia/agents/<id>/agent.py) reportedHEALTH: erroringaia agent status, even when it ran perfectly — the first thing a user sees after authoring an agent told them their working agent was broken. Nowgaia agent statusreports a custom agent's health from whether it can actually be loaded: a working agent showshealthy, and a genuinely broken one (e.g. one that never implements_register_tools) still showserrorwith a cause that names the real failure.Closes #2268
Test plan
python -m pytest tests/unit/test_hub_lifecycle.py -xpassespython util/lint.py --allpasses~/.gaia/agents/<id>/agent.py(withAGENT_ID,AGENT_NAME, and a_register_toolsimplementation) and confirmgaia agent statusreports ithealthy_register_toolsand confirmgaia agent statusreports iterrorwith a cause naming_register_tools🔍 Technical details
Root cause.
_default_loader()insrc/gaia/hub/lifecycle.pyknew only two probes:builtin(presence in the registry) and installed-wheel (gaia.agentsetuptools entry point). File-based custom agents (source == "custom_python") are exec'd directly from disk and have no entry point by construction, so the loader always fell through to the wheel branch and raised "installed on disk but exposes no 'gaia.agent' entry point" — reportingerrorfor all of them unconditionally.Health signal — discoverable, hardened to concrete. For
custom_pythonthe signal is the registry's own successful discovery (module imported,Agentsubclass found), the same way a registered builtin is proof it loaded. Discovery alone isn't enough, though: an agent that never implements the abstract_register_toolsimports and registers fine but can never be constructed. So the new branch also inspectscls.__abstractmethods__and raises (→error) naming the unimplemented method(s). This deliberately does not construct the agent — per the issue's constraint,gaia agent statusmust not trigger constructor side effects. (gaia agent run/#2242 remains the "constructible" test; this is the lighter "discoverable + concrete" one.)Changes.
src/gaia/hub/lifecycle.py—_default_loadergains acustom_pythonbranch before the wheel probe; builtin and wheel paths are untouched.src/gaia/agents/registry.py—AgentRegistrationgains an optionalagent_classfield, populated in_load_python_agentfrom the already-imported class. This surfaces the discovered class to the health check with no re-import/no construction; it staysNonefor builtins/installed wheels (lazy-import factories), which the branch never reads.tests/unit/test_hub_lifecycle.py— covers concrete custom agent → healthy, abstract custom agent → error naming_register_tools, the class-absent defensive fallback, plus builtin and installed-wheel regression probes.Verified.
tests/unit/test_hub_lifecycle.py(23 passed) andtests/unit/agents/test_registry.pypass;python util/lint.py --all --fixclean.