Context
Surfaced while auditing the skills + memory adapters for the same failure-loudness gap fixed in #15. Their _post_graphql returns silently on every failure mode — but unlike the canvas slash commands (#15), the right behavior here is silent fallback (callers MUST keep their file fallback per the module docstring contract). So the slash-command-style loudness fix doesn't translate.
What DOES translate is: when an operator opts into graph mode by setting DEVAGENTIC_SKILLS_GRAPH=1 or DEVAGENTIC_MEMORY_GRAPH=1 but the graph silently isn't being consulted (because auth missing, URL wrong, or devagentic unreachable), they have no diagnostic surface. hermes doctor does not probe devagentic at all — searched hermes_cli/doctor.py, zero DEVAGENTIC-related checks.
Repro
export DEVAGENTIC_SKILLS_GRAPH=1
export DEVAGENTIC_MEMORY_GRAPH=1
# (no DEVAGENTIC_API_KEY set, or wrong DEVAGENTIC_BASE_URL)
hermes doctor
# → no mention of the graph at all; user has no way to know lookups are silently failing
Fix
Add a _check_devagentic_graph() section to hermes_cli/doctor.py. Inert when both graph_enabled() flags are False (the byte-stable default for users who never wired devagentic). When either flag is True, send one { __typename } GraphQL probe and surface the specific failure kind:
auth failed — set DEVAGENTIC_API_KEY (401/403)
not found at {url}/graphql (404)
unreachable at {url}/graphql (URLError / OSError / Timeout)
DEVAGENTIC_USER_ID unresolved (no env, no profile)
reachable — auth + user_id OK (200, no errors)
Self-contained in doctor.py — no changes to the adapter modules (their loss-tolerant contract stays correct for their actual callers).
Out of scope
- Adding
last_error_text symmetry to skills/memory adapters (mirroring canvas). Their consumers don't need it; only doctor would, and doctor can probe directly.
- Auto-detecting which graph mode failed first. The probe doesn't differentiate skills-vs-memory because both use the same GraphQL endpoint with the same auth.
Filed by hermes-maintainer (PowerCreek). PR incoming.
Context
Surfaced while auditing the skills + memory adapters for the same failure-loudness gap fixed in #15. Their
_post_graphqlreturns silently on every failure mode — but unlike the canvas slash commands (#15), the right behavior here is silent fallback (callers MUST keep their file fallback per the module docstring contract). So the slash-command-style loudness fix doesn't translate.What DOES translate is: when an operator opts into graph mode by setting
DEVAGENTIC_SKILLS_GRAPH=1orDEVAGENTIC_MEMORY_GRAPH=1but the graph silently isn't being consulted (because auth missing, URL wrong, or devagentic unreachable), they have no diagnostic surface.hermes doctordoes not probe devagentic at all — searchedhermes_cli/doctor.py, zeroDEVAGENTIC-related checks.Repro
Fix
Add a
_check_devagentic_graph()section tohermes_cli/doctor.py. Inert when bothgraph_enabled()flags are False (the byte-stable default for users who never wired devagentic). When either flag is True, send one{ __typename }GraphQL probe and surface the specific failure kind:auth failed — set DEVAGENTIC_API_KEY(401/403)not found at {url}/graphql(404)unreachable at {url}/graphql(URLError / OSError / Timeout)DEVAGENTIC_USER_ID unresolved(no env, no profile)reachable — auth + user_id OK(200, no errors)Self-contained in doctor.py — no changes to the adapter modules (their loss-tolerant contract stays correct for their actual callers).
Out of scope
last_error_textsymmetry to skills/memory adapters (mirroring canvas). Their consumers don't need it; only doctor would, and doctor can probe directly.Filed by hermes-maintainer (PowerCreek). PR incoming.